3

我在使用该功能时遇到问题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

现在,当我切换到对话框时,它就像一个魅力。在下面的代码中,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;
}

Could you please point out where I am going wrong? As far as I can see, other than the creation and destruction of the main window, there seems to be no difference at all between the two of them. Am I missing something on the SHAutoComplete docs that states it can only be used on edit boxes inside dialogs?

4

1 回答 1

5

You are using a filtered message loop so any messages for the drop down are not being processed. Pass NULL as the second parameter to GetMessage

于 2012-08-12T19:43:09.200 回答