2010-04-05 3 views
2

간단한 메뉴가 있고 간단한 작업을 수행하는 윈도우 폼이 있습니다. 메뉴 막대, 메시지 펌프 등의 모든 기능을 가진 다른 윈도우 폼을 만들 수 있어야합니다. 별도의 스레드로 작업의 결과를 두 번째 창에 공유 할 수 있습니다.CreateWindowsEx()를 사용하여 두 개의 윈도우 만들기

I.E.

1) A 형은 형태 B가 별도의 쓰레드로 열리고 열리고

2) A 형은 행하는 형태 A가 B를

4) B 형 표시 폼을 메모리를 통해 결과를 전달

3) 운전 결과

나는 그것에 대해 갈 방법에 관해서 혼란 스럽다, 주 응용 프로그램은 잘 실행되지만 첫 번째 창이 이미 존재하는 경우 두 번째 창을 추가하는 방법을 모르겠다. CreateWindow를 사용하면 다른 창을 만들 수 있지만 다시 메시지 펌프에 액세스하는 방법을 모르므로 두 번째 창에서 WM_CREATE와 같은 특정 이벤트에 응답 할 수 있다고 생각합니다.

나는 그것이 의미가 있기를 바랍니다.

감사합니다.

편집 :

나는 두 번째 창을 시도했고,이 컴파일 않지만, 어떤 창 atall에 구축 보여주지.

////////////////////// 
// WINDOWS FUNCTION // 
////////////////////// 
LRESULT CALLBACK WindowFunc(HWND hMainWindow, UINT message, 
          WPARAM wParam, LPARAM lParam) 
{ 
    //Fields 
    WCHAR buffer[256]; 
    struct DiceData storage; 
    HWND hwnd; 

    // Act on current message 
    switch(message)  
    { 
    case WM_CREATE: 
     AddMenus(hMainWindow); 

     hwnd = CreateWindowEx(
      0, 
      "ChildWClass", 
      (LPCTSTR) NULL, 
      WS_CHILD | WS_BORDER | WS_VISIBLE, 
      0, 
      0, 
      0, 
      0, 
      hMainWindow, 
      NULL, 
      NULL, 
      NULL); 

     ShowWindow(hwnd, SW_SHOW); 

     break; 

왜 이런 일이 발생하는지 제안 해주세요.

편집 2 :

이가 전부입니다 나는이 권리를 구현하고있어하지만 난 다른 윈도우 생성과 일치하도록 시도했다, 난 아무 생각도 없어.

////////////////// 
// WINDOWS MAIN // 
////////////////// 
int WINAPI WinMain(HINSTANCE hThisInst, HINSTANCE hPrevInst, 
        LPSTR lpszArgs, int nWinMode) 
{ 
    // Declaration of window class (used to register program), 
    // handle to window (returned by CreateWindow) 
    // and windows message (holds messages received from windows) 
    WNDCLASS wcl; 
    WNDCLASS scl; 
    HWND hwnd; 
    MSG msg; 

    // Name of window and window class 
    LPCWSTR szWinName = L"DiceRoller - Producer"; 
    LPCWSTR szClassName = L"DiceRollProd"; 

    LPCWSTR szCWinName = L"Dice - Consumer"; 
    LPCWSTR szCClassName = L"DiceRollCon"; 

    // Set up the windows class struct 
    wcl.hInstance = hThisInst; 
    wcl.lpszClassName = szClassName; 
    wcl.lpfnWndProc = WindowFunc; 
    wcl.style = 0; 
    wcl.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
    wcl.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wcl.lpszMenuName = NULL; 
    wcl.cbClsExtra = 0; 
    wcl.cbWndExtra = 0; 
    wcl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 

    // Set up the windows class struct 
    scl.hInstance = hThisInst; 
    scl.lpszClassName = szCClassName; 
    scl.lpfnWndProc = WindowFunc; 
    scl.style = 0; 
    scl.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
    scl.hCursor = LoadCursor(NULL, IDC_ARROW); 
    scl.lpszMenuName = NULL; 
    scl.cbClsExtra = 0; 
    scl.cbWndExtra = 0; 
    scl.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 

    // Register the windows class 
    if(!RegisterClass(&wcl)) 
    { 
     return 0; 
    } 

    if(!RegisterClass(&scl)) 
    { 
     return 0; 
    } 

    // Create the main window 
    hwnd = CreateWindowEx(0, 
     szClassName, 
     szWinName, 
     WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN, 
     100, 
     100, 
     400, 
     400, 
     HWND_DESKTOP, 
     NULL, 
     hThisInst, 
     NULL); 


    // Show the main window 
    ShowWindow(hwnd, nWinMode); 
    UpdateWindow(hwnd); 

    // Main message processing loop 
    while(GetMessage(&msg, NULL, 0, 0)) 
    { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
    return (int)msg.wParam; 
} 



////////////////////// 
// WINDOWS FUNCTION // 
////////////////////// 
LRESULT CALLBACK WindowFunc(HWND hMainWindow, UINT message, 
          WPARAM wParam, LPARAM lParam) 
{ 
    //Fields 
    WCHAR buffer[256]; 
    struct DiceData storage; 
    HWND hwnd; 

    // Act on current message 
    switch(message)  
    { 
    case WM_CREATE: 
     AddMenus(hMainWindow); 

     hwnd = CreateWindowEx(
     0, 
     "ChildWClass", 
     (LPCTSTR) NULL, 
     WS_CHILD | WS_BORDER | WS_VISIBLE, 
     CW_USEDEFAULT, // x location 
     CW_USEDEFAULT, // y location 
     400, // width 
     300, // height 
     hMainWindow, 
     NULL, 
     NULL, 
     NULL); 

     ShowWindow(hwnd, SW_SHOW); 
     UpdateWindow(hwnd); 

     break; 
+0

어, 정말로 다른 프로세스가 필요하다고 생각하지 않습니다. 아마도 다른 스레드를 원할 것입니다. – SamB

+0

수정 됨! 내 실수. –

+0

두 번째 CreateWindow 호출에서 첫 번째 hwnd를 ovewriting합니다. 2 개의 창을 추적하고 표시하려면 2 개의 행 높이가 필요합니다. ;> – dthorpe

답변

2

CreateWindow() 호출에서 위치 및 크기 매개 변수에 0을 전달합니다.
과 같이 당신의 WM_CREATE 케이스를 수정 해보십시오 ..

case WM_CREATE: 
    AddMenus(hMainWindow); 

    hwnd = CreateWindowEx(
     0, 
     "ChildWClass", 
     (LPCTSTR) NULL, 
     WS_CHILD | WS_BORDER | WS_VISIBLE, 
     CW_USEDEFAULT, // x location 
     CW_USEDEFAULT, // y location 
     400, // width 
     300, // height 
     hMainWindow, 
     NULL, 
     NULL, 
     NULL); 

    ShowWindow(hwnd, SW_SHOW); 

    break; 

여기에 당신이 적어도 자식 창에/관련 w를 수행하려는 생각의 해석이다. (나는 아직도 두 번째 스레드가 필요한 이유를 볼 수 있지만, 하나의 문제를 한 번에 ..하지 않음)

#include <windows.h> 
LRESULT CALLBACK TheWndProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP) { 
    HDC hdc; 
    HWND hwother; 

    switch(msg) { 
    case WM_CREATE: 
     hwother = 
     CreateWindowEx(0, "TerribleClassName100405", "child title", 
      WS_OVERLAPPEDWINDOW, 
      100, 100, // location 
      200, 160, // size 
      (HWND)hwnd, // parent 
      (HMENU)NULL, 
      NULL, 
      NULL); 
     ShowWindow(hwother, SW_SHOW); 

     break; 

    case WM_CHAR: // quit app using escape key 
     switch(LOWORD(wP)) { 
     case 27: 
      SendMessage(hwnd, WM_CLOSE, 0, 0); 
      return 0; 
     } 
     break; 

    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 
    } 
    return DefWindowProc(hwnd, msg, wP, lP); 
} 

LRESULT CALLBACK AltWndProc(HWND hwnd, UINT msg, WPARAM wP, LPARAM lP) { 
    HDC hdc; 

    switch(msg) { 
    case WM_CREATE: 
     break; 

    case WM_CHAR: // quit app using X 
     switch(LOWORD(wP)) { 
     case 'X': 
      SendMessage(hwnd, WM_CLOSE, 0, 0); 
      return 0; 
     } 
     break; 

    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 
    } 
    return DefWindowProc(hwnd, msg, wP, lP); 
} 

void registerCustomWindows(HINSTANCE hInst) { 
    WNDCLASSEX wc1; 
    WNDCLASSEX wc2; 

    wc1.lpszClassName = "TerribleClassName040914"; 
    wc1.hInstance = hInst; 
    wc1.lpfnWndProc = TheWndProc; 
    wc1.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
    wc1.cbSize = sizeof(wc1); 
    wc1.cbClsExtra = 0; 
    wc1.cbWndExtra = 0; 
    wc1.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
    wc1.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 
    wc1.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc1.hbrBackground = GetStockObject(WHITE_BRUSH); 
    wc1.lpszMenuName = NULL; 
    RegisterClassEx(&wc1); 

    wc2.lpszClassName = "TerribleClassName100405"; 
    wc2.hInstance = hInst; 
    wc2.lpfnWndProc = AltWndProc; 
    wc2.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC; 
    wc2.cbSize = sizeof(wc2); 
    wc2.cbClsExtra = 0; 
    wc2.cbWndExtra = 0; 
    wc2.hIcon = LoadIcon(NULL, IDI_APPLICATION); 
    wc2.hIconSm = LoadIcon(NULL, IDI_APPLICATION); 
    wc2.hCursor = LoadCursor(NULL, IDC_ARROW); 
    wc2.hbrBackground = GetStockObject(WHITE_BRUSH); 
    wc2.lpszMenuName = NULL; 
    RegisterClassEx(&wc2); 
} 

int WINAPI WinMain(HINSTANCE hThis, HINSTANCE hPrev, LPSTR cml, int iCS) { 
    MSG msg; 
    HWND hwnd; 

    registerCustomWindows(hThis); 

    hwnd = CreateWindowEx(0, "TerribleClassName040914", "two windows skeleton", 
     WS_OVERLAPPEDWINDOW, 
     CW_USEDEFAULT, CW_USEDEFAULT, // location 
     640, 480, // size 
     (HWND)NULL, // parent 
     (HMENU)NULL, 
     hThis, 
     NULL); 

    ShowWindow(hwnd, SW_SHOWNORMAL); 
    UpdateWindow(hwnd); 

    while(GetMessage(&msg, NULL, 0, 0)) { 
     TranslateMessage(&msg); 
     DispatchMessage(&msg); 
    } 
    return msg.wParam; 
} 

내가 파일에 정확한 코드가 demo.c라는 것을 가지고, 2005 년을 표현 MS 비주얼 스튜디오를 사용 줄을 사용하여 컴파일하십시오.

cl demo.c user32.lib gdi32.lib 

.. 그리고 두 개의 창이 나타납니다. 두 개의 창 클래스가 있다는 사실을 구별하기 위해 ESC와 다른 대문자 X를 눌러 그 중 하나가 종료됩니다.

두 번째 응답 게시에 대해 사과드립니다. 내 다른 하나는 매우 일반화 된 응답이었고 OP가 더 자세한 내용을 제공 했으므로 이제는 OBE 일 수 있습니다.

+0

아직 하나의 창만 표시되며 예제와 Microsoft MSDN이 동일해야합니다. –

+0

솔루션을 제공해 주셔서 감사합니다. 나는 광산을 재검토하고 이것이 효과가없는 이유를 알아볼 것입니다. 양해 해 주셔서 대단히 감사합니다. –

4

당신은 다른를 생성 할 수 있어야한다, 실제로 창에 모두 윈도우 이벤트를 공급한다 CreateWindow 함수(), 표준 GetMessage 함수() DispatchMessage() 루프를 사용하여 보조 창. Windows는 어떻게 든 CreateWindow에서 호출을하는 스레드를 해당 창의 Windows 이벤트와 연관시키고 GetMessage() 호출을 통해이 둘의 이벤트를 피드에 제공합니다. 두 번째 창에 대한 이벤트를 처리 할 두 번째 스레드를 만들 필요가 없습니다.

이제 CreateWindow() 호출과 동일한 창 클래스 이름을 전달하면 동일한 창 클래스의 인스턴스가 두 개 있어야하며이를 구별하는 방법은 wndproc에서 DispatchMessage가 제공하는 것입니다 관련 윈도우에 대한 윈도우 핸들. 그렇게하면 응용 프로그램에 정적 인 데이터가 사실상 두 창 사이의 공유 리소스가됩니다. 예를 들어 WM_PAINT를 백업하기 위해 화면 외부의 비트 맵/장치 컨텍스트를 정적으로 선언하면 갑자기 두 윈도우 모두 이벤트에 대한 응답으로 페인팅 할 수 있습니다. 이러한 종류의 얽힘을 얻는 방법은 스레드간에 데이터를 쉽게 공유 할 수 있도록 지불하는 대가입니다.

사용자가 수행하려는 작업이 사용자가 느린 제어를 경험하는 지점까지 메시지 대기열 처리를 묶지 않는다면 하나의 스레드 만 사용하여 얻을 수 있습니다.

+0

@JustJeff 나는 그것을 구현하는 데 문제가 있음에도 불구하고 내가 겪고 자하는 것이 무엇인지 생각해 보았다. –

+0

방금 ​​게시물과 비슷한 코드를 테스트했지만 하위 창에 일반 오래된 BUTTON을 사용했습니다. WM_CREATE와 같은 범위에서 자식 창을 만들 수 있어야하고 부모 창에서 WS_CLIPCHILDREN을 잊어 버린 경우 자식 창이 액세스 할 수 없다는 것을 확인했습니다. – JustJeff

+0

두 번 확인하기 만하면 처음에 메뉴를 추가 할 때와 동일한 창을 만들 수 있습니다. 콤보 박스와 버튼을 만드는 웹 페이지를 본 적이 있습니다. –

관련 문제