使用Windows.h C ++时如何避免使用全局变量

时间:2018-07-05 16:57:15

标签: c++ visual-studio winapi switch-statement global-variables

所以我有以下代码,我确实有两个问题:

如何避免使用全局变量来存储有关     以后使用?我显然无法向WndProc添加更多参数或     更改返回类型。我还可以做些什么来存储新信息     待会儿吗?

为什么我不能使用LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam); vector<string> *strings = reinterpret_cast<vector<string>*>(lpcs->lpCreateParams); 代码在switch语句之外,然后引用指向switch语句内部字符串向量的指针?我不明白为什么这样做时超出了范围(我也不经常使用switch语句)。我还尝试过在switch语句外声明一个size变量,以存储在switch语句内声明后的向量长度,但是我当然遇到了同样的问题。

void Select(vector<string>& ret)
{
    HINSTANCE hInstance = GetModuleHandle(NULL); //NULL = the current process
    WNDCLASSW wc = { 0 };
    MSG  msg;

    wc.lpszClassName = L"Selection1";
    wc.hInstance = hInstance;
    wc.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
    wc.lpfnWndProc = WndProc;
    wc.hCursor = LoadCursor(0, IDC_ARROW);
    wc.style = CS_DBLCLKS;

    RegisterClassW(&wc);
    CreateWindowW(wc.lpszClassName, L"Selection",
        WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_SYSMENU,
        CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, &ret);

    while (GetMessage(&msg, NULL, 0, 0)) {

        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg,
    WPARAM wParam, LPARAM lParam) {
    bool checked = true;
    HWND text, button;
    //hwnd is parent window
    switch (msg) {

case WM_CREATE: {
    text = CreateWindow("STATIC", "Selection:", WS_VISIBLE | WS_CHILD, 20, 20, 300, 25, hwnd, NULL, NULL, NULL);
    button = CreateWindow("BUTTON", "Exit", WS_VISIBLE | WS_CHILD | WS_BORDER, 500, 500, 80, 25, hwnd, (HMENU)0, NULL, NULL);
    LPCREATESTRUCT lpcs = reinterpret_cast<LPCREATESTRUCT>(lParam);
    vector<string> *strings = reinterpret_cast<vector<string>*>(lpcs->lpCreateParams);
    int j = 23;
    checkVectorSize = strings->size(); //checkVectorSize is a global variable
    for (int i = 1; i != strings->size() + 1; i++)
    {
        cout << (*strings)[i - 1].c_str() << endl;
        CreateWindowA("button", (*strings)[i - 1].c_str(),
            WS_VISIBLE | WS_CHILD | BS_CHECKBOX | WS_OVERLAPPED,
            20, j, 185, 35, hwnd, (HMENU)i,
            NULL, NULL);
        CheckDlgButton(hwnd, 0, BST_UNCHECKED);

        j = j + 25;
    }


    break;
}
case WM_COMMAND: {
    int i = wParam;
    if (i == 0) //LOWORD(wParam)
    {
        for (int j = 0; j != checkVectorSize; j++)
        {
            if (IsDlgButtonChecked(hwnd, j + 1) == true)
            {
                checkResultIndexes.push_back(j);
                //GetClassName(hwnd,)
                //checkResult.push_back();
            }

        }
        PostMessage(hwnd, WM_CLOSE, 0, 0);
        //::MessageBeep(MB_ICONERROR);
        //::MessageBox(hwnd, "Button was clicked", "", MB_OK);
        break;
    }
    checked = IsDlgButtonChecked(hwnd, i);
    if (checked) {

        CheckDlgButton(hwnd, i, BST_UNCHECKED);
        SetWindowTextW(hwnd, L"");
    }
    else {
        CheckDlgButton(hwnd, i, BST_CHECKED);
        SetWindowTextW(hwnd, L"");
    }
    break;
}
case WM_DESTROY: {

    PostQuitMessage(0);
    break;
}
}
return DefWindowProcW(hwnd, msg, wParam, lParam);

2 个答案:

答案 0 :(得分:3)

您可以使用带有Get标志的SetWindowLongPtrW / GWLP_USERDATA将任意数据与窗口关联。在WM_CREATE处理程序中:

SetWindowLongPtrW(hwnd, GWLP_USERDATA, reinterpter_cast<::LONG_PTR>(strings));

要稍后检索储值:

vector<string> *strings = reinterpret_cast<vector<string>*>(GetWindowLongPtrW(hwnd, GWLP_USERDATA));
assert(strings);

请注意,您必须确保此指针指向的对象能够生存足够长的时间。

答案 1 :(得分:1)

lParam仅在LPCREATESTRUCT消息期间引用WM_CREATE。如您所描述的那样,将其强制转换为该操作的其他尝试将失败,并带有读取访问冲突。 (请参见https://docs.microsoft.com/en-us/windows/desktop/winmsg/wm-create)。请勿尝试将其转换为WM_CREATE

之外的类型