질문과 답변

윈도우즈API 정복 1권 363p~366p 예제 Childs 질문드립니다. 날짜:2023-12-10 5:17:29 조회수:210
작성자 : 황금가물치
포인트 : 63
가입일 : 2022-05-06 15:33:18
방문횟수 : 55
글 9개, 댓글 9개
소개 : 안녕하세요. 윈도우즈api를 공부하기위하여 가입했습니다. 잘 부탁드립니다.
작성글 보기
쪽지 보내기
#include<Windows.h>

HINSTANCE g_hInst;
LPCTSTR MyClassName = TEXT("FistClass");

HWND hWndMain,hC1,hC2,hC3;
HBRUSH hRedBrush, hBlueBrush, hGreenBrush;

LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildLeftProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildTopProc(HWND, UINT, WPARAM, LPARAM);
LRESULT CALLBACK ChildBottomProc(HWND, UINT, WPARAM, LPARAM);

int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow) {
    
    WNDCLASS wndclass{};
    HWND hWnd{};
    MSG msg{};
    g_hInst = hInstance;

    hRedBrush = (HBRUSH)CreateSolidBrush(RGB(255,0,0));
    hGreenBrush = (HBRUSH)CreateSolidBrush(RGB(0,255,0));
    hBlueBrush = (HBRUSH)CreateSolidBrush(RGB(0,0,255));


    wndclass.lpfnWndProc = WndProc;
    wndclass.lpszClassName = MyClassName;
    wndclass.hInstance = hInstance;
    wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
    wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
    wndclass.cbWndExtra = 0;
    wndclass.cbClsExtra = 0;
    wndclass.lpszMenuName = NULL;
    wndclass.hbrBackground = NULL;
    wndclass.style = CS_HREDRAW | CS_VREDRAW;
    RegisterClass(&wndclass);

    wndclass.hbrBackground = hRedBrush;
    wndclass.lpfnWndProc = ChildLeftProc;
    wndclass.lpszClassName = TEXT("ChildLeft");
    RegisterClass(&wndclass);

    wndclass.hbrBackground = hGreenBrush;
    wndclass.lpfnWndProc = ChildTopProc;
    wndclass.lpszClassName = TEXT("ChildTop");
    RegisterClass(&wndclass);

    wndclass.hbrBackground = hBlueBrush;
    wndclass.lpfnWndProc = ChildBottomProc;
    wndclass.lpszClassName = TEXT("ChildBottom");
    RegisterClass(&wndclass);

    hWnd = CreateWindowExW(NULL, MyClassName, MyClassName,WS_OVERLAPPEDWINDOW|WS_VSCROLL|WS_HSCROLL,CW_USEDEFAULT, CW_USEDEFAULT,
        CW_USEDEFAULT, CW_USEDEFAULT, NULL,(HMENU)NULL,hInstance,NULL);

    ShowWindow(hWnd, nCmdShow);
    UpdateWindow(hWnd);

    hWndMain = hWnd;

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

    DeleteObject(hRedBrush);
    DeleteObject(hGreenBrush);
    DeleteObject(hBlueBrush);

    
    return((int)msg.wParam);
}

LRESULT CALLBACK WndProc(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam) {

    RECT crt{};

    switch (iMessage){
    case WM_CREATE:
        hC1 = CreateWindowExW(NULL, TEXT("ChildLeft"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,
            0, 0, 0, 0, hWnd, (HMENU)0, g_hInst, NULL);
        hC2 = CreateWindowExW(NULL, TEXT("ChildTop"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,
            0, 0, 0, 0, hWnd, (HMENU)0, g_hInst, NULL);
        hC3 = CreateWindowExW(NULL, TEXT("ChildBottom"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN,
            0, 0, 0, 0, hWnd, (HMENU)0, g_hInst, NULL);
        return(0);
    case WM_SIZE:
        if (wParam != SIZE_MINIMIZED) {
            GetClientRect(hWnd, &crt);
            MoveWindow(hC1,0,0,300,crt.bottom,TRUE);
            MoveWindow(hC2,300,0,crt.right-300,150,TRUE);
            MoveWindow(hC3,300,150,crt.right-300,crt.bottom-150,TRUE);
        }
        return(0);
    case WM_DESTROY:
        PostQuitMessage(0);
        return(0);
    }
    return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

------------------------------------------------------------------------------------------------------------

1) hRedBrush, hBlueBrush, hGreenBrush는 wWinMain함수에서 자동으로 삭제가 안되는 지요? 자동으로 삭제가 안되기에
    DeleteObject를 사용하는지 궁금합니다.
2) hRedBrush, hBlueBrush, hGreenBrush는 DeleteObject로 삭제하는 것이 맞는지 궁금합니다. hdc를 생성하여 selectobject로
   선택후 다른 OldhRedBrush등을 생성하여 재선택한후 삭제하는게 아닌 지 궁금합니다. 책 164p처러 해야 하는 것처럼
   배웠는데 여기서는 바로 삭제하니 궁금합니다. hdc를 생성하여 배경을 주지 않아 메모리 영향에 끼치는 것이 없어 저렇게
   삭제하는 것인지 궁금합니다.
3) hC1,hC2,hC3의 윈도우 생성 시 hParent(부모윈도우)는 WndProc의 인자 hWnd로 사용하는 것이 맞는지 궁금합니다. 앞에서
   해당 hWnd는 메시지 입력 인자로 배웠는데 해당 인자가 부모 윈도우 인자로 이해하면 되는지 궁금합니다. hInstance는
   wWinMain인자로 사용했지만 부모윈도우는 WndProc으로 사용해서 궁금합니다. 위의 hWndMain이 부모윈도우 인자로
  생각했는데 아예 그려지지도 않고 궁금합니다.
4) wParam!=SIZE_MINIMIZED는 왜 사용하는지 궁금합니다. 알려주시기 바랍니다.



김민수
媛쒕큺뿭씠留덉궗吏 紐⑹긽룞留뚮궓썑湲 愿怨좊룞異쒖옣꺏 슦蹂대㈃踰덇컻留뚮궓 떒꽦硫댁꽦씤留쏆궗吏 슜븞硫대쾲媛쒕쭔궓 湲덉궗硫댁텧옣留뚮궓 씪肄붿뒪뀒뼇留먯눥븨紐 泥二쇱텧옣留뚮궓,蹂대졊異쒖옣留덉궗吏,솕꽦異쒖옣留덉궗吏-留덉궗吏媛씠뱶 룞씤吏 빆臾 猷뚮굹 룞씤吏 諛붾줈뿰援 꽮뒪슫룞쉶留뚰솕 넻쁺異쒖옣留뚮궓 쁺벑룷援ъ텧옣留덉궗吏 留쏆궗吏

쑉븯留쏆쭛 遺꾩쐞湲곗쥕移댄럹 봽옉뒪뿬뻾 젣二쇱뿬뻾以 異쒖씠옄怨꾩궛 뿊李⑥씠굹슫異쒓툑 移대뱶寃곗젣 怨깆갹留쏆쭛 룆諛뺤쑁븘以 썾뵫 삤뒛븯뒛 諛⑹퐬뿬뻾 肄붾끂뒪諛붾떎겕땲뒪룞씤吏 釉붾윭 뙆겕 꽌걧踰꾩뒪 닔而룹쓣 留뚰솕닔媛 룞빐異쒖옣븞留

목록보기 삭제 수정 신고 스크랩

작가K 12월10일 11:39:11  

1) 변수를 삭제하는 것과 그 변수가 기억하는 객체를 삭제하는 것은 다릅니다. hRedBrush가 지역 변수여서 변수 자체는 WinMain이 종료되면 삭제되지만 이 변수에 저장해 놓은 빨간색 브러시는 삭제되지 않습니다. 그래서 원론적으로 만든 객체는 직접 삭제해 줘야 합니다.

2) 그리기에 직접 사용한 객체라면 DC에서 먼저 선택 해제한 후 삭제하는 것이 맞습니다. 그러나 이 예제의 세 브러시는 DC에 선택한게 아니라 윈도우 클래스의 배경 브러시로 지정한 것이므로 선택해제할 방법이 없습니다. 윈도우는 잠시 후 파괴될 예정이고 윈도우 클래스도 사라질 예정이므로 그냥 삭제하면 됩니다.

3) WM_CREATE 메시지를 받은 주체가 메인 윈도우이므로 WndProc의 인수로 전달된 hWnd가 부모 윈도우 맞습니다. 메인 윈도우를 생성하는 중에 차일드를 생성하는 겁니다. hWndMain도 부모 윈도우가 맞으며 어디서나 메인 윈도우로 참조할 수 있는 변수입니다. 그러나 이 값을 대입하는 시점이 CreateWindowEx보다 늦기 때문에 WM_CREATE 메시지를 처리하는 중에는 아직 값이 대입되지 않은 상태입니다. CreateWindowEx가 생성한 윈도우 핸들을 리턴해야 메인 윈도우를 알 수 있으므로 생성중에는 WndProc으로 전달되는 hWnd릉 릭는 방법밖에 없습니다.

4) 메인 윈도우의 크기가 변경되면 WM_SIZE 메시지가 날라오고 이때 차일드의 영역을 적당히 조정하도록 했습니다. 다만, 윈도우가 최소화될 때는 어차피 안 보이기 때문에 불필요한 동작을 할 필요가 없습니다. 물론 해도 상관없습니다만 부모 윈도우의 크기가 0이 되므로 차칫하면 0으로 나누기 에러가 발생할 수 있습니다. 

황금가물치 12월12일 12:07:50  

1번, 2번, 3번 설명은 명쾌한 해답을 주셔서 감사합니다. 아직 4번은 wParam은 키보드 값입력으로 알고 있는데 아직도 헷갈리네요.
좀더 공부한 뒤 다시 질문드리도록 하겠습니다.

gcyong 12월26일 4:04:15  

4번에서 wParam은 키보드 값입력이 아닙니다. 전달되는 메시지 종류(iMessage)에 따라 다르며, iMessage가 WM_SIZE인 경우 크기가 변경 요청된 타입입니다. (https://learn.microsoft.com/en-us/windows/win32/winmsg/wm-size)

즉, 예제에서는 크기 조정 이벤트가 발생했을 때 차일드 윈도우의 크기를 조정하되, 최소화일 경우 화면상에 그려지지 않으므로 불필요한 동작이 되어 굳이 하지 않도록 조건으로 체크 한 것입니다.

wParam이 입력한 키 값인 경우는 iMessage가 WM_KEYDOWN 같은 메시지일 때만 맞는 말씀입니다.


로그인하셔야 댓글을 달 수 있습니다.