2017-08-06 51 views
-2

经过一段时间的WinAPI实验后,我得到了一个带有按钮的窗口。该代码是把我的窗口过程,看起来像这样:调用函数来创建WinAPI按钮不会执行任何操作

std::vector<HWND> buttons; 
HWND window; 

LRESULT CALLBACK CSwindowProc(HWND window, unsigned int message, WPARAM shortParam, LPARAM longParam) { 
    switch (message) { 
    case WM_CREATE: 
     buttons.push_back(
      CreateWindow(_T("BUTTON"), _T("OK"), WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 
       10, 10, 100, 100, window, NULL, (HINSTANCE)GetWindowLongPtr(window, GWL_HINSTANCE), NULL) 
     ); 
     break; 
    case WM_DESTROY: PostQuitMessage(0); break; 
    default: return DefWindowProc(window, message, shortParam, longParam); break; 
    } 
    return 0; 
} 

请注意“按钮”是HWND向量和“窗口”只是用CreateWindow的初始化的HWND。这些片段的上下文与本问题最后的代码相同。

为了简化我的工作,我决定将按钮创建代码移动到一个新函数(CSnewButton)中。然后,我从窗口过程中删除了按钮创建代码,并向CSnewButton()添加了一个调用。此时代码如下所示:

std::vector<HWND> buttons; 
HWND window; 

void CSnewButton() { 
    buttons.push_back(
     CreateWindow(_T("BUTTON"), _T("OK"), WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 
      10, 10, 100, 100, window, NULL, (HINSTANCE)GetWindowLongPtr(window, GWL_HINSTANCE), NULL) 
    ); 
} 

LRESULT CALLBACK CSwindowProc(HWND window, unsigned int message, WPARAM shortParam, LPARAM longParam) { 
    switch (message) { 
    case WM_CREATE: 
     CSnewButton(); 
     break; 
    case WM_DESTROY: PostQuitMessage(0); break; 
    default: return DefWindowProc(window, message, shortParam, longParam); break; 
    } 
    return 0; 
} 

令人惊讶的是,窗口上不再显示该按钮。通过简单地将过程中的代码移动到过程所调用的函数中,该按钮就消失了。 我很快做了一些调试以排除一些问题。我在函数中添加了一个消息框,并且消息框确实出现,所以函数被调用。一旦添加到CSnewButton函数,C++内联修饰符不会帮助我的情况。我在编译时或运行时都看不到任何错误或警告。 (我不会感到惊讶),对WinAPI的误解(可能是罪魁祸首),或者是对我的代码非常非常明显的错误(我会也不会感到惊讶)。无论如何,我想知道为什么将按钮创建代码移入一个函数会带走代码的功能,并解决这个问题(如果可能的话)。

的完整代码展示了问题:

#include <windows.h> 
#include <tchar.h> 
#include <vector> 

HINSTANCE instance; 
HWND window; 

std::vector<HWND> buttons; 

//This function inexplicably does not create the button, however, if you were 
//to take it's contents and paste them over a call to this function, it works 
//fine. 
void CSnewButton() { 
    buttons.push_back(
     CreateWindow(_T("BUTTON"), _T("OK"), WS_TABSTOP | WS_VISIBLE | WS_CHILD | BS_DEFPUSHBUTTON, 
      10, 10, 100, 100, window, NULL, (HINSTANCE)GetWindowLongPtr(window, GWL_HINSTANCE), NULL) 
    ); 
} 

LRESULT CALLBACK CSwindowProc(HWND window, unsigned int message, WPARAM shortParam, LPARAM longParam) { 
    switch (message) { 
    case WM_CREATE: 
     CSnewButton(); // Issue Here 
     break; 
    case WM_DESTROY: PostQuitMessage(0); break; 
    default: return DefWindowProc(window, message, shortParam, longParam); break; 
    } 
    return 0; 
} 

void CScreateWindow() { 
    WNDCLASSEX cclass = { 
     sizeof(WNDCLASSEX), CS_VREDRAW | CS_HREDRAW, 
     CSwindowProc, 0, 0, instance, NULL, LoadCursor(NULL, IDC_ARROW), 
     (HBRUSH)(COLOR_WINDOW + 1), NULL, _T("MyClass"), NULL 
    }; 
    if (!RegisterClassEx(&cclass)) { 
     MessageBox(NULL, _T("CSControlApp failed to register window."), _T("CSControlApp failure"), MB_OK | MB_ICONERROR); return; 
    } 
    window = CreateWindow(cclass.lpszClassName, _T("My Window"), WS_OVERLAPPEDWINDOW^WS_THICKFRAME, 
     CW_USEDEFAULT, CW_USEDEFAULT, 600, 600, NULL, NULL, instance, NULL); 
    if (!window) { 
     MessageBox(NULL, _T("CSControlApp failed to create window."), _T("CSControlApp failure"), MB_OK | MB_ICONERROR); return; 
    } 
} 

int CALLBACK WinMain(HINSTANCE h, HINSTANCE p, LPSTR cmd, int show) { 
    instance = h; 
    CScreateWindow(); 
    ShowWindow(window, show); 
    UpdateWindow(window); 
    MSG msg; 
    while (GetMessage(&msg, NULL, 0, 0)) { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
    return 0; 
} 
+2

请将代码作为代码发布,而不是图片。 – Ron

+0

我不得不认为将代码截屏并将其上传到问题比将其复制/粘贴更困难。我只是不明白为什么人们继续这样做。 – pinkfloydx33

+0

我完成了。底部的代码不应该显示按钮。要使其显示按钮,请将CSnewButton的内容粘贴到CSwindowProc中CSnewButton的调用上。同样,我期望的行为是让按钮显示,即使从CSnewButton调用。 –

回答

2

这是一个C语言的问题。你有两个具有相同名称的独立变量,并且让你感到困惑。

HWND window; // This is a global variable 

LRESULT CALLBACK CSwindowProc(HWND window, ...) // This is a parameter 

里面CSWindowProc当你说window你得到的参数。 OutsideCsWindowProc当你说window时,你得到了全局变量,它在你尝试使用它的时候还没有被初始化。 (在CScreateWindowCreateWindow呼叫尚未返回。)

您可以通过给CSnewButton参数解决问题:

void CSnewButton(HWND window) 

,并相应地称之为:

case WM_CREATE: 
    CSnewButton(window); 
    break; 

为了避免将来任何类似的混淆,最好是完全删除全局变量。

相关问题