c++ winapi不可能创建2个控件

Posted

技术标签:

【中文标题】c++ winapi不可能创建2个控件【英文标题】:c++ winapi impossible to create 2 controls 【发布时间】:2013-08-24 14:23:07 【问题描述】:

我正在尝试创建包含richedit 控件和列表框控件的窗口, 问题是我创建的第二个控件没有出现。 我的意思是:

case WM_CREATE: // In main window procedure

    /* Center the main window */
    This->CenterWindow(hwnd);

    /* Initialize the clients list */
    This->InitListClients(hwnd);

    /* Initialize the server log */
    This->InitEditLog(hwnd);

    return 0;

如果InitListClients函数是第一个,只会显示列表框, 如果InitEditLog 排在第一位,则只会显示richedit。

以下是函数:

void ApostleServer::InitEditLog(HWND &_hwnd)

    LoadLibrary(TEXT("Riched32.dll"));
    hEditLog = CreateWindowEx(WS_EX_STATICEDGE, "richedit", "bla", WS_CHILD | WS_VISIBLE | ES_MULTILINE, 10, 10, 390, 310, _hwnd, NULL, (HINSTANCE)GetWindowLong(_hwnd, GWL_HINSTANCE), NULL);


void ApostleServer::InitListClients(HWND &_hwnd)

    hListClients = CreateWindowEx(WS_EX_STATICEDGE, "listbox", "bla", WS_CHILD | WS_VISIBLE | LBS_NOTIFY, 550, 20, 150, 150, _hwnd, NULL, (HINSTANCE)GetWindowLong(_hwnd, GWL_HINSTANCE), NULL);

我是 winapi 的新手,我找不到这个问题的解决方案。 谢谢。

编辑: 正如我所评论的,问题的原因是使用类成员。 这是我编写的完整代码并且有同样的问题:

#include <Windows.h>
#include <stdlib.h>

class Server

public:

    /* Fields */
    MSG* msg;
    WNDCLASSW* wc;
    HWND hListClients;
    HWND hEditLog;

    /* Methods */
    void InitEditLog(HWND &_hwnd)
    
        LoadLibrary(TEXT("Riched32.dll"));
        hEditLog = CreateWindowExW(WS_EX_STATICEDGE, L"richedit", L"Text", WS_CHILD | WS_VISIBLE | ES_MULTILINE, 10, 10, 390, 306, _hwnd, (HMENU)2, (HINSTANCE)GetWindowLong(_hwnd, GWL_HINSTANCE), NULL);
    

    void InitListClients(HWND &_hwnd)
    
        // Here I'm using hListClients class member, and that what cause the problem (I will see only the list on the window)
        hListClients = CreateWindowExW(WS_EX_STATICEDGE, L"listbox", L"asd", WS_CHILD | WS_VISIBLE | LBS_NOTIFY, 410, 10, 160, 306, _hwnd, (HMENU)1, (HINSTANCE)GetWindowLong(_hwnd, GWL_HINSTANCE), NULL);
        // If I was only creating the listbox (without returning handler), I will see the listbox and the richedit.
    

    static LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
    

        Server* This = (Server*)GetWindowLongW(hwnd, GWL_USERDATA);

        switch(msg)
        
            case WM_CREATE:
            
                /* Initialize the clients list */
                This->InitListClients(hwnd); // Attention that I called this function first.

                /* Initialize the server log */
                This->InitEditLog(hwnd);
                // If I would call this function first, I will see only the richedit.

                return 0;
            

            case WM_DESTROY:
            
                PostQuitMessage(0);
                return 0;
            
        

        return DefWindowProcW(hwnd, msg, wParam, lParam);
    

    Server(HINSTANCE &_hInstance)
    
        msg = new MSG;
        wc = new WNDCLASSW;
        wc->style = CS_HREDRAW | CS_VREDRAW;
        wc->cbClsExtra = 0;
        wc->cbWndExtra = 0;
        wc->lpszClassName = L"ApostleServer";
        wc->hInstance = _hInstance;
        wc->hbrBackground = GetSysColorBrush(COLOR_3DFACE);
        wc->lpszMenuName = NULL;
        wc->lpfnWndProc = WndProc;
        wc->hCursor = LoadCursor(NULL, IDC_ARROW);
        wc->hIcon = LoadIcon(NULL, IDI_APPLICATION);

        RegisterClassW(&(*wc));
        CreateWindowW(wc->lpszClassName, L"Apostle Server", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 600, 400, 0, 0, _hInstance, 0);

        while(GetMessage(&(*msg), NULL, 0, 0))
        
            TranslateMessage(&(*msg));
            DispatchMessage(&(*msg));
        

    
;

int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PWSTR pCmdLine, int nCmdShow)

    Server* srvr = new Server(hInstance);
    return 0;

【问题讨论】:

第一段代码比较奇怪。首先,this 指针在 C++ 中没有大写。所以我假设这是一个指向代表窗口的 C++ 对象的变量的名称。但是,为什么要将窗口句柄作为参数传递,而不是将其作为成员变量进行访问呢?无论如何,不​​是什么破坏了你的代码,只是一些令人困惑的事情。 另一个问题是您使用的是 8 字节的 ANSI 字符串,尽管它是 2013 年。所有 Windows 应用程序现在都应该是 Unicode。确保已定义 UNICODE 符号,并且您的字符串文字以 L 为前缀。 不过,代码对我来说很好用。所以问题出在你在这里展示给我们的东西之外。您可以通过创建一个新项目并一次添加一段代码来自行调试。 好吧,将字符串更改为 unicode 解决了我的问题,但有一个问题,是否有一个 CreateWindow 函数可以接收 unicode 字符串并具有扩展样式? CreateWindowEx 就是它的名字。 【参考方案1】:

通过在WM_CREATE 消息上创建控件解决了问题(但不是设置控件处理程序!),并在创建主窗口后设置控件处理程序。

WM_CREATE消息:

    case WM_CREATE:
    
        /* Center the main window */
        This->CenterWindow(hwnd);

        /* Initialize the clients list */
        This->InitListClients(hwnd);

        /* Initialize the server log */
        This->InitEditLog(hwnd);


        return 0;
    

主窗口创建后:

RegisterClassW(&(*wc));
hMainWindow = CreateWindowW(wc->lpszClassName, L"Apostle Server", WS_OVERLAPPEDWINDOW | WS_VISIBLE, 100, 100, 600, 400, 0, 0, _hInstance, 0);

/* Set controls handlers */
hListClients = GetDlgItem(hMainWindow, IDC_LISTCLIENTS);
hEditLog = GetDlgItem(hMainWindow, IDC_EDITLOG);

InitEditLogInitListClients 函数:

void ApostleServer::InitEditLog(HWND &_hwnd)

    LoadLibrary(TEXT("Riched32.dll"));
    CreateWindowExW(WS_EX_STATICEDGE, L"richedit", L"Text", WS_CHILD | WS_VISIBLE | ES_MULTILINE, 10, 10, 390, 306, _hwnd, (HMENU)IDC_EDITLOG, (HINSTANCE)GetWindowLong(_hwnd, GWL_HINSTANCE), NULL);


void ApostleServer::InitListClients(HWND &_hwnd)

    CreateWindowExW(WS_EX_STATICEDGE, L"listbox", L"asd", WS_CHILD | WS_VISIBLE | LBS_NOTIFY, 410, 10, 160, 306, _hwnd, (HMENU)IDC_LISTCLIENTS, (HINSTANCE)GetWindowLong(_hwnd, GWL_HINSTANCE), NULL);

【讨论】:

以上是关于c++ winapi不可能创建2个控件的主要内容,如果未能解决你的问题,请参考以下文章

如何更改静态文本控件(winapi)的字体?

winApi使用c++创建进程

WinAPI 中的编辑控件文本无法更改

如何在纯 C++ 中高效快速地清理我的 GDI 对象 - winapi(不是 .net,c#)?

winapi - 如何使用所有控件禁用组框框架

控件的背景颜色(winapi)