2017-05-15 4 views
1

저는 win32 API를 사용하여 인터페이스를 구축하고 있으며 다른 클래스의 모든 클래스를 스레드로 관리하여 메인에서 작업을 계속하고 싶었습니다. 는이 코드가 있습니다C++ Win32 Api GetMessage 닫는 프로그램 내부 스레드

WindowManager.h

class UIManager::WindowManager { 
private: 
    //Class data 
    HINSTANCE hInstance; 
    WNDCLASSEX winClass; /* Data structure for the windowclass */ 
    MSG msg; 
    HWND hwnd; 
    //Window Data 
    LPCSTR wiName; 
    int startX = 250; 
    int startY = 150; 
    int endX = 544; 
    int endY = 375; 
    //Private managers 
    void makeWindow(); 
public: 
    WindowManager(HINSTANCE & hInstance, std::string wiName = "Window Name"); 
    void show(); 
}; 

WindowManager.c (I 네임 스페이스 내부의 클래스를 가지고 그 스레드가 있습니다 내가 찾은 유일한 방법이기 때문에 내가 바인딩을 사용 은 "GetMessage 함수는"전이 때 나를 대신 창이 WM_CREATE를 실행하고 제대로 보여, 심지어 실행

#include "WindowManager.h" 

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 

//Private 
// 
void UIManager::WindowManager::makeWindow() 
{ 
    int ms = GetMessage(&msg, 0, 0, 0); //I do this to see if it gets to 
    while (GetMessage(&msg, NULL, 0, 0)) { //this part, but never happens 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
} 

//Public 
// 
UIManager::WindowManager::WindowManager(HINSTANCE & hInstance, std::string wiName) 
{ 
    this->wiName = wiName.c_str(); 
    this->hInstance = hInstance; 
    winClass.cbSize = sizeof(winClass); 
    winClass.hInstance = hInstance; 
    winClass.lpszClassName = this->wiName; 
    winClass.lpfnWndProc = WndProc; //Execution callback 
    //Load default editable ellements 
    winClass.hCursor = LoadCursor(0, IDC_ARROW);  /*Default*/ 
    winClass.hIcon = LoadIcon(NULL, IDI_APPLICATION); /*Default*/  //Alt+Tab Dialog 
    winClass.hbrBackground = GetSysColorBrush(COLOR_3DFACE); 
    winClass.lpszMenuName = NULL;      /* No menu */ 
    RegisterClassEx(&winClass); 

    //Create Window 
    hwnd = CreateWindowEx(
     0, 
     this->wiName,   /* Title Class */ 
     this->wiName,   /* Title Text */ 
     WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_VISIBLE | WS_OVERLAPPEDWINDOW, 
     startX,       /* X Start */ 
     startY,       /* Y Start */ 
     endX,       /* The programs width */ 
     endY,       /* and height in pixels */ 
     HWND_DESKTOP,     /* The window is a child-window to desktop */ 
     NULL,       /* No menu */ 
     hInstance,    /* Program Instance handler */ 
     NULL 
    ); 
    SetWindowPos(hwnd, 0, 0, 0, 20, 20, 0); 
} 

void UIManager::WindowManager::show() 
{ 
    std::thread listener(std::bind(&WindowManager::makeWindow, this)); 
    listener.detach(); 
} 

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{ 
    switch (msg) 
    { 
    case WM_CREATE: 
    { //This part is executed 
     //...blablabla 
     break; 
    } 

    case WM_COMMAND: 
    {//This part is never executed 
     //...blablabla 
     break; 
    } 

    case WM_DESTROY: 
    {//This part is never executed 
     //...blabla 
     PostQuitMessage(0); 
     break; 
    } 
    } 
    return DefWindowProc(hwnd, msg, wParam, lParam); 
} 

오류)를 던지는 컴파일 만합니다 어떤 실수 나 그와 같은 것을 던지지 않고 즉시 프로그램을 종료합니다.

GetMessage의 값을 int에 추가하여 디버그 모드에서 "while"상태가되는지 확인하지만 발생합니다. 던지고 있거나 프로그램을 닫지 못하게 할 수있는 오류를 볼 수있는 방법이 있습니까? 아니면 스레드 내부에서 "GetMessage"를 잘못 호출하고있는 것입니까?

+2

코드가 없습니다. [mcve]를 제공 할 수 있습니까? 나는 makeWindow에 대한 인수가 유효한지 의심 스럽다. 왜 당신이 참조 매개 변수로'MSG'를 전달할 지 상상할 수 없습니다. 내 기대는 그 것이 지역 변수가 될 것입니다. 따라서 코드에 결함이있는 것으로 예상되지만 볼 수는 없습니다. –

+0

@DavidHeffernan 테스트로서의 문제인지 그리고이 부분을 빠뜨리는 것을 잊었는지 알기 위해 그렇게했습니다. 코드 – OnelioD

+0

을 편집하겠습니다 [mcve]가 없으면 추측 할 수 있습니다. 도움이 필요한 코드를 표시하는 것이 정말 대단한가요? 내가 준 링크를 따라 가니? 그렇다면 다시 한 번 읽고 아주 조심스럽게 읽으십시오. –

답변

0

코드는 몇 가지 문제가있다 :

  • 당신은 하나 개의 스레드에서 창을 만들 수 있지만 다른 스레드에서 meesage 루프를 실행 해보십시오. GetMessage은 호출하는 스레드에 속한 창의 메시지 만 처리합니다.
  • 백그라운드 스레드 처리 메시지를 기다리지 않고 대신 메인 스레드에서 실행을 계속 종료하고 응용 프로그램을 종료합니다.
  • GetMessage이 반환 한 값을 검사하지 않고 부울로 사용합니다.

배경 UI 스레드를 만들고 싶다면 거기에 모든 창 생성 코드를 옮기고 스레드에 join을 호출해야합니다. 메시지 루프는 다음과 같아야합니다.

::MSG msg; 
for(;;) 
{ 
    auto const res{::GetMessage(&msg, NULL, 0, 0))}; 
    if(0 < res) 
    { 
     ::TranslateMessage(&msg); 
     ::DispatchMessage(&msg); 
    } 
    else if(0 == res) 
    { // PostQuitMessage was called... 
     break; 
    } 
    else 
    { // an error occurred... 
     break; 
    } 
} 
+0

'GetMessage'를 부울로 취급하는 표준 메시지 루프는이 경우에 문제가 없습니다. https://blogs.msdn.microsoft.com/oldnewthing/20130322-00/?p=4873 –