2012-11-15 4 views
1

3 개의 창을 표시하려고하는데 왜 창 2를 만들지 못하는 이유가 확실하지 않습니다. 그것은 첫 번째 창을 만들고 다른 두 개는 똑같이했습니다. 여기 WIN32 다중 창

코드입니다 :

#include <Windows.h> 

// Store handles to the main window and application instance globally. 
HWND  ghMainWnd = 0; 
HWND  ghSecdWnd = 0; 
HWND  ghThrdWnd = 0; 
HINSTANCE ghAppInst = 0; 

//======================================================================================== 
// WINDOW 1 
// Step 1: Define and implement the window procedure. 
LRESULT CALLBACK 
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 

    switch(msg) 
    { 
    // Handle left mouse button click message. 
    case WM_LBUTTONDOWN: 
     MessageBox(hWnd, "Left Mouse Button Click", "Message", MB_OK); 
     return 0; 

    // Handle key down message. 
    case WM_KEYDOWN: 
     if(wParam == VK_ESCAPE) 
      if(MessageBox(hWnd, "Are you sure?", "Quit", MB_YESNO) == IDYES) 
       DestroyWindow(ghMainWnd); 
     return 0; 

    // Handle destroy window message. 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     return 0; 
    } 

    // Forward any other messages we didn't handle to the default window procedure. 
    return DefWindowProc(hWnd, msg, wParam, lParam); 

} 
//======================================================================================== 
// WINDOW 2 
//======================================================================================== 
LRESULT CALLBACK 
WndProc2(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 

    switch(msg) 
    { 
    // Handle down arrow pressed. 
    case WM_KEYDOWN: 
     if(wParam == VK_DOWN) 
      MessageBox(hWnd, "Down arrow pressed 2.", "Information", MB_OK); 
     return 0; 
    case WM_LBUTTONDOWN: 
     MessageBox(hWnd, "Window 2", "Window 2", MB_OK); 
     return 0; 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     return 0; 
    } 

    return DefWindowProc(hWnd, msg, wParam, lParam); 
} 
//======================================================================================== 
// WINDOW 3 
//======================================================================================== 
LRESULT CALLBACK 
WndProc3(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 

    switch(msg) 
    { 
    // Handle down arrow pressed. 
    case WM_KEYDOWN: 
     if(wParam == VK_DOWN) 
      MessageBox(hWnd, "Down arrow pressed 3.", "Information", MB_OK); 
     return 0; 
    case WM_LBUTTONDOWN: 
     MessageBox(hWnd, "Window 3", "Window 3", MB_OK); 
     return 0; 
    case WM_DESTROY: 
     PostQuitMessage(0); 
     return 0; 
    } 

    return DefWindowProc(hWnd, msg, wParam, lParam); 
} 

// WinMain: Entry point for windows application. 
int WINAPI 
    WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR cmdLine, int showCmd) 
{ 

    // Save handle to application instance. 
    ghAppInst = hInstance; 

    // Step 2: Fill out a WNDCLASS instance. 
    WNDCLASS wc; 
    wc.style   = CS_HREDRAW | CS_VREDRAW; 
    wc.lpfnWndProc = WndProc; 
    wc.cbClsExtra = 0; 
    wc.cbWndExtra = 0; 
    wc.hInstance  = ghAppInst; 
    wc.hIcon   = ::LoadIcon(0, IDI_APPLICATION); 
    wc.hCursor  = ::LoadCursor(0, IDC_ARROW); 
    wc.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); 
    wc.lpszMenuName = 0; 
    wc.lpszClassName = "MyWndClassName"; 

    // Window 2 
    WNDCLASS wc2; 
    wc2.style   = CS_HREDRAW | CS_VREDRAW; 
    wc2.lpfnWndProc = WndProc2; 
    wc2.cbClsExtra = 0; 
    wc2.cbWndExtra = 0; 
    wc2.hInstance  = ghAppInst; 
    wc.hIcon   = ::LoadIcon(0, IDI_APPLICATION); 
    wc2.hCursor  = ::LoadCursor(0, IDC_ARROW); 
    wc2.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); 
    wc2.lpszMenuName = 0; 
    wc2.lpszClassName = "MyWndClassTwo"; 

    // Window 3 
    WNDCLASS wc3; 
    wc3.style   = CS_HREDRAW | CS_VREDRAW; 
    wc3.lpfnWndProc = WndProc3; 
    wc3.cbClsExtra = 0; 
    wc3.cbWndExtra = 0; 
    wc3.hInstance  = ghAppInst; 
    wc3.hIcon   = ::LoadIcon(0, IDI_APPLICATION); 
    wc3.hCursor  = ::LoadCursor(0, IDC_ARROW); 
    wc3.lpszMenuName = 0; 
    wc3.lpszClassName = "MyWndClassThree"; 


    // Step 3: Register with WNDCLASS instance with windows. 
    RegisterClass(&wc); 
    RegisterClass(&wc2); 
    RegisterClass(&wc3); 

    // Step 4: Create the window, and save the handle in global window handle variable ghMainWnd. 
    ghMainWnd = ::CreateWindow("MyWndClassName", "Window 1", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 0, 0, 500, 500, 0, 0, ghAppInst, 0); 
    ghSecdWnd = ::CreateWindow("MyWndClassTwo", "Window 2", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 510, 0, 500, 500, 0, 0, ghAppInst, 0); 
    ghThrdWnd = ::CreateWindow("MyWndClassThree", "Window 3", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL, 0, 510, 500, 500, 0, 0, ghAppInst, 0); 

    if(ghMainWnd == 0) 
    { 
     ::MessageBox(0, "Create Window 1 - Failed", 0, 0); 
     return false; 
    } 

    if(ghSecdWnd == 0) 
    { 
     ::MessageBox(0, "Create Window 2 - Failed", 0, 0); 
     return false; 
    } 

    if(ghThrdWnd == 0) 
    { 
     ::MessageBox(0, "Create Window 3 - Failed", 0, 0); 
     return false; 
    } 

    // Step 5: Show and update the window. 
    ShowWindow(ghMainWnd, showCmd); 
    UpdateWindow(ghMainWnd); 

    ShowWindow(ghSecdWnd, showCmd); 
    UpdateWindow(ghSecdWnd); 

    ShowWindow(ghThrdWnd, showCmd); 
    UpdateWindow(ghThrdWnd); 

    // Step 6: Enter the message loop and don't quit until a WM_QUIT message is received. 
    MSG msg; 
    ZeroMemory(&msg, sizeof(MSG)); 

    while(GetMessage(&msg, 0, 0, 0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 

    // Return exit code back to operating system. 
    return (int)msg.wParam; 

} 

그것은 오류가 발생하지 않지만, ghSecdWnd == 0에 해당 오류 메시지가 표시됩니다. 당신이 겪고있는 한, 두 번째 창을 생성 한 후 GetLastError()를 호출 창 3.

한 (그러나 세 번째 작성하기 전에) "Cannot find the window class."에 결과 :

+3

두 번째'CreateWindow' 호출 후에'GetLastError'를 호출 해 보았습니까? 왜 실패했는지에 관해 밝힐 수 있습니다. http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx – atkretsch

+0

방법을 알아낼 수 없습니까? – Cypras

+0

@Cypras, 나는 내 대답에서 다소 설명했다. 함수가 어떻게 작동하는지 검색하고 동작을 기반으로 조치를 취해야합니다. 가능한 경우 오류를 확인해야합니다. – chris

답변

5

이 두 가지 문제가 있습니다.

wc.hIcon = ::LoadIcon(0, IDI_APPLICATION); 

당신이 실제로 필요로하는 wc2의 아이콘을 설정하는 것입니다 : 클래스 설정을 보면, 다음과 같은 완료했습니다. 두 번째 클래스를 등록 할 때 RegisterClass의 반환 값을 확인하더라도 의 문제를 나타내는 "The parameter is incorrect."의 오류가 발생합니다. 또한 코드에서 오류를 잡기위한 이전 위치이기 때문에 항상 좋은 점입니다.


둘째, 세 번째 창에 문제가 있습니다. 배경 브러시를 설정하지 않았습니다. wc3 설정이 줄을 추가합니다 : 당신은 항상 실패 할 경우 기능이 무엇을 찾아 적절한 조치를 취하도록 문서를 확인해야합니다

wc3.hbrBackground = (HBRUSH)::GetStockObject(WHITE_BRUSH); 

. 예를 들어 CreateWindow이 실패하면 반환 값은 NULL이고 GetLastError을 호출하면 자세한 정보를 얻을 수 있습니다. 함수 단위로이 작업을 수행해야합니다. 다음은 Window 2의 두 가지 주요 기능을 사용한 예입니다. GetStockObject과 같은 다른 기능도 실패 할 수 있습니다.

if (!RegisterClass(&wc2)) { //returns 0 if failed 
    std::cout << "Failed to register class: "; 
    std::cout << GetLastError() << '\n'; //or however you want to show it 
} 

if (!(ghSecdWnd = CreateWindow(/*...*/)) { //or ghSecdWnd = ...; if (!ghSecdWnd) 
    std::cout << "Failed to create window: "; 
    std::cout << GetLastError() << '\n'; //look at FormatMessage for a message 
} 

첫째, RegisterClass보고, 당신은 실패에 0을 반환하고 그래서 출력을, 확장 된 오류 정보를 그 GetLastError()를 호출 할 수 있다고 반환 값 아래를 참조하십시오. CreateWindow도 마찬가지이지만, HWND이 포인터이기 때문에 NULL입니다. 얻은 오류 코드를 MSDN System Error Codes 문서에서 확인하거나 과 FORMAT_MESSAGE_FROM_SYSTEM을 사용하여 확인할 수 있습니다.

+0

어떻게 GetLastError 함수를 호출 했습니까? 나는 그것을 이해할 수 없었다. – Cypras

+0

Visual Studio 2012에서 도구 아래의 오류 조회라는 오류 코드를 입력하여 문자열을 가져올 수 있습니다. VS2012가 포함되어 있는지 또는 추가했는지 기억이 나지 않지만'FormatMessage'를 설정하고 싶지 않을 때 매우 유용합니다. – chris