简体   繁体   English

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

[英]SHAutoComplete on edit control without dialog boxes

I am having trouble using the function SHAutoComplete . 我在使用SHAutoComplete函数时遇到问题。 It simply does not work correctly when I use it on a edit box whose parent window is not a dialog box. 当我在父窗口不是对话框的编辑框中使用它时,它无法正常工作。

The auto-complete functionality seems to be working fine, but the rendering of the drop-down list with the possible candidates based on what was typed on the edit box is very messed up. 自动完成功能似乎工作正常,但下拉列表与基于编辑框中键入的内容的可能候选项的呈现非常混乱。 Basically only the borders of the drop-down are shown. 基本上只显示下拉菜单的边框。 The borders are rendered wide enough to fit the possible suggestions, but the suggestions themselves are never drawn. 边框的宽度足以满足可能的建议,但建议本身从未被绘制。 Even the drop-down list background color is wrong. 即使是下拉列表背景颜色也是错误的。 It is as if it was never painted and remains with the original parent window color. 就好像它从未被绘制过并保持原始父窗口颜色。

And if the number of suggestions is big enough so the drop-down needs a scroll-bar, the scrollbar also does not get rendered correctly - the arrows do not get drawn. 如果建议的数量足够大,因此下拉列表需要滚动条,滚动条也无法正确呈现 - 箭头不会被绘制。

On both cases, with or without scrollbars, the drop-down list does not accept mouse input, ie, I cannot click on the items. 在这两种情况下,无论是否有滚动条,下拉列表都不接受鼠标输入,即我无法点击这些项目。 If I press the "down" key on the keyboard while the drop-down is being shown, it kind of works as expected. 如果我在显示下拉菜单时按下键盘上的“向下”键,它会按预期工作。 After the second or third press the items finally start to appear. 在第二次或第三次按下后,项目最终开始出现。 But the scrollbar still is does not get rendered correctly. 但滚动条仍然无法正确呈现。

If instead of registering my own windows class I simply use a dialog with ::DialogBoxParam() , then it all goes as expected. 如果不是注册我自己的Windows类,我只需使用带有::DialogBoxParam()的对话框,然后一切按预期进行。 The auto-complete works without any problems at all. 自动完成工作完全没有任何问题。

Here is what I am doing. 这就是我在做的事情。 This code will register a window class, create the main window, create an edit box and then call SHAutoComplete on it. 此代码将注册一个窗口类,创建主窗口,创建一个编辑框,然后在其上调用SHAutoComplete It must be linked with Shlwapi.lib 它必须与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;
}       

That code produces the following: 该代码产生以下内容:

  1. the drop-down when a scroll bar is needed http://www.abload.de/img/shautocomplete_2i1sk4.jpg 需要滚动条时的下拉菜单http://www.abload.de/img/shautocomplete_2i1sk4.jpg

  2. the drop-down after a couple of presses to the "down" key. 几次按下“向下”键后的下拉菜单。 Notice how the scroll bar still is not rendered correctly. 请注意滚动条仍然无法正确呈现。 http://www.abload.de/img/shautocomplete_3efsgw.jpg http://www.abload.de/img/shautocomplete_3efsgw.jpg

Now, when I switch to Dialog Boxes, works like a charm. 现在,当我切换到对话框时,就像一个魅力。 In the code below, IDD_DIALOG1 is simply an empty dialog box resource, created automatically by the IDE. 在下面的代码中,IDD_DIALOG1只是一个空的对话框资源,由IDE自动创建。

Here is the relevant part of the rc file 这是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

And here is the code that uses it 以下是使用它的代码

// 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? 我在SHAutoComplete文档中遗漏了一些内容,表明它只能在对话框中的编辑框中使用吗?

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 将NULL作为GetMessage的第二个参数传递

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM