2017-08-06 63 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; 

爲了避免將來任何類似的混淆,最好是完全刪除全局變量。

相關問題