没有对话框的编辑控件上的SHAutoComplete

时间:2012-08-12 19:34:07

标签: c++ c winapi

我在使用函数SHAutoComplete时遇到问题。当我在父窗口不是对话框的编辑框中使用它时,它无法正常工作。

自动完成功能似乎工作正常,但下拉列表的渲染与可能的候选基于编辑框中输入的内容非常混乱。基本上只显示下拉菜单的边框。边框的宽度足以满足可能的建议,但建议本身从未被绘制。即使是下拉列表背景颜色也是错误的。就好像它从未被绘制过并保持原始父窗口颜色。

如果建议的数量足够大,因此下拉列表需要滚动条,滚动条也无法正确呈现 - 箭头不会被绘制。

在这两种情况下,无论是否有滚动条,下拉列表都不接受鼠标输入,即我无法点击这些项目。如果我在显示下拉菜单时按下键盘上的“向下”键,它会按预期工作。在第二次或第三次按下后,项目最终开始出现。但滚动条仍然无法正确呈现。

如果不是注册我自己的Windows类,而只是使用::DialogBoxParam()的对话框,那么一切都按预期进行。自动完成工作完全没有任何问题。

这是我正在做的事情。此代码将注册一个窗口类,创建主窗口,创建一个编辑框,然后在其上调用SHAutoComplete。它必须与Shlwapi.lib

相关联
// this code must be linked with Shlwapi.lib

#include <Windows.h>
#include <Shlwapi.h>


// name of the class that will be created for the main window
static const char WindowClassName[] = "SHAutoCompleteDoesNotWorkWithoutADialogWindowClassName";


// the main window procedure
static LRESULT CALLBACK WindowProc(
    HWND   hwnd,
    UINT   uMsg,
    WPARAM wParam,
    LPARAM lParam)
{
    switch(uMsg)
    {   
        case WM_CREATE:
        {
            HWND hwndEdit = ::CreateWindowEx(
                0,
                "EDIT",
                0,
                WS_CHILD | WS_VISIBLE,
                10, 
                10, 
                300,
                25,
                hwnd, 
                NULL,
                NULL,
                0);     

            ::SHAutoComplete(hwndEdit, SHACF_DEFAULT);

            return 0;
        }            

        case WM_DESTROY:
            ::PostQuitMessage(1);
            return 0;

        default:
            return ::DefWindowProc(hwnd, uMsg, wParam, lParam);
    }
}


// the app entry point
int CALLBACK WinMain(
    HINSTANCE hInstance,
    HINSTANCE hPrevInstance,
    LPSTR    lpCmdLine,
    int       nCmdShow)
{
    ::CoInitialize(NULL);

    WNDCLASSEX wcex    = {0};
    wcex.cbSize        = sizeof(wcex);
    wcex.style         = CS_OWNDC | CS_HREDRAW | CS_VREDRAW ;
    wcex.lpfnWndProc   = WindowProc;
    wcex.hInstance     = hInstance;        
    wcex.lpszClassName = WindowClassName;
    wcex.hbrBackground = (HBRUSH)(COLOR_BTNFACE+1); 

    ATOM atom = ::RegisterClassEx(&wcex);

    HWND hwnd = ::CreateWindowEx(
        0,
        MAKEINTATOM(atom),
        "SHAutoComplete Test",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE |  WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        CW_USEDEFAULT,
        NULL,
        NULL,
        hInstance,
        NULL);

    MSG msg;
    while(::GetMessage(&msg, hwnd, 0, 0) > 0)
    {
        ::TranslateMessage(&msg);
        ::DispatchMessage(&msg);
    }

    ::UnregisterClass((LPCTSTR)atom, NULL);

    ::CoUninitialize();

    return 0;
}       

该代码产生以下内容:

  1. 需要滚动条时的下拉列表 http://www.abload.de/img/shautocomplete_2i1sk4.jpg

  2. 几次按下“向下”键后的下拉菜单。请注意滚动条仍然无法正确呈现。 http://www.abload.de/img/shautocomplete_3efsgw.jpg

  3. 现在,当我切换到对话框时,就像魅力一样。在下面的代码中,IDD_DIALOG1只是一个空的对话框资源,由IDE自动创建。

    以下是rc文件的相关部分

    IDD_DIALOG1 DIALOGEX 0, 0, 316, 185
    STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | WS_POPUP | WS_CAPTION | WS_SYSMENU
    CAPTION "Dialog"
    FONT 8, "MS Shell Dlg", 400, 0, 0x1
    BEGIN
    END
    

    以下是使用它的代码

    // this code must be linked with Shlwapi.lib
    
    #include <windows.h>
    #include <Shlwapi.h>
    
    #include "Resource.h"
    
    
    BOOL CALLBACK DialogProc(
        HWND   hwnd,
        UINT   uMsg,
        WPARAM wParam,
        LPARAM lParam)
    {    
    
        switch(uMsg)
        {        
            case WM_INITDIALOG:
            {
                HWND hwndEdit = ::CreateWindowEx(
                    0,
                    "EDIT",
                    0,
                    WS_VISIBLE | WS_CHILD,                    
                    0, 
                    0, 
                    300,
                    20,
                    hwnd, 
                    NULL,
                    NULL,
                    0);      
    
                ::SHAutoComplete(hwndEdit, SHACF_DEFAULT);
    
                return 1;
            }
    
    
            case WM_CLOSE:            
                ::EndDialog(hwnd, 0);
                return 1;   
    
    
            default:
                return 0;
        }
    }
    
    
    
    int WINAPI WinMain(
        HINSTANCE hInstance,
        HINSTANCE hPrevInstance,
        LPSTR     lpCmdLine,
        int       nShowCmd)
    {       
        ::CoInitialize(NULL);
    
        ::DialogBoxParam(
            NULL,
            MAKEINTRESOURCE(IDD_DIALOG1),
            NULL,
            DialogProc,
            0);    
    
        ::CoUninitialize();
    
        return 0;
    }
    

    你能指出我哪里出错吗?据我所知,除了主窗口的创建和破坏之外,两者之间似乎没有任何区别。我在SHAutoComplete文档中遗漏了哪些内容,表明它只能在对话框中的编辑框中使用?

1 个答案:

答案 0 :(得分:5)

您正在使用过滤的消息循环,因此不会处理下拉列表的任何消息。将NULL作为第二个参数传递给GetMessage