질문과 답변

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

int sx, sy, oldx, oldy;
BOOL bNowDraw;

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

LRESULT CALLBACK WndProc(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;

    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 = (HBRUSH)CreateSolidBrush(RGB(255, 255, 255));
    wndclass.style = CS_HREDRAW | CS_VREDRAW;

    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);

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

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

    HDC hdc{};
    bNowDraw = FALSE;

    switch (iMessage){
    
    case WM_LBUTTONDOWN:
        sx = lParam & 0x0000FFFF;
        sy = (lParam>>16) & 0x0000FFFF;
        oldx = sx;
        oldy = sy;
        bNowDraw = TRUE;
        return(0);
    case WM_MOUSEMOVE:
        if (bNowDraw == TRUE) {
            hdc = GetDC(hWnd);
            SetROP2(hdc, R2_NOT);
            MoveToEx(hdc, sx, sy, NULL);
            LineTo(hdc, oldx, oldy);
            oldx = lParam & 0x0000FFFF;
            oldy = (lParam >> 16) & 0x0000FFFF;
            MoveToEx(hdc, sx, sy, NULL);
            LineTo(hdc, oldx, oldy);
            ReleaseDC(hWnd, hdc);
        }
        return(0);
    case WM_LBUTTONUP:
        bNowDraw = FALSE;
        hdc = GetDC(hWnd);
        MoveToEx(hdc, sx, sy, NULL);
        LineTo(hdc, oldx, oldy);
        return(0);
    case WM_DESTROY:
        PostQuitMessage(0);
        return(0);
    }
    return(DefWindowProc(hWnd, iMessage, wParam, lParam));
}

--------------------------------------------------------------------------------------------------------------------------------------
전역변수로 지정된 BOOL bNowDraw 상에 FALSE를 대입시키지 않고 WndProc함수안에서 bNowDraw를 FALSE로 정의하면 
그리기가 안 되는데 이유를 알고싶습니다. 또한 책 예제에 WM_LBUTTONUP 내에 MoveToEx와 LineTo가 없어도 제대로 작동되는데 해당 부분은 오타인지 궁금합니다. 답변 부탁드립니다.



김민수
끂꽌룞梨꾪똿 뿭궪뿭異쒖옣꺏 삤踰꾩썙移 굹뿉寃뚮컯븘以 而ㅻㅻ땲떚넄猷⑥뀡 李쎈㈃留뚮궓썑湲 꽭醫낅━븞留 쓽솗 냼媛쒗똿 씡궛異쒖옣留뚮궓쐯솕꽦異쒖옣꺏쐯怨좎뼇異쒖옣留덉궗吏 뾼떎硫댁콈똿 뵲쑜븳 슦利덈쭏궎 뿬룞깮理쒕㈃留앷 겕由ъ뒪留덉뒪異쒖옣븷씤 諛뺣퀝샇 슜씤뼇吏렂뀡 븘以뚮쭏蹂댁뜲 룞臾멸뎄異쒖옣留덉궗吏 쇅援뼵땲

꽌洹룷移댄럹 몮吏몃뒗궗옉엯땲떎 뵺뒪 꽦궓留 뼱由곗씠 궗옉뫁씠 湲됱뿬뻾 떊샎遺遺씪긽 吏곸옣씤뒪洹몃옩 궡씪 而ㅽ뵾룞븘由 넚뙆肄쒓구꺏 엯泥댄룷넗씤삎 냼븙留 떆뒪꽣 吏곸옣씤誘명똿

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

작가K 12월10일 11:28:50  

bNowDraw를 WndProc 안에서 정의하면 지역 변수가 되며 WndProc이 호출될 때마다, 즉 메시지가 발생할 때마다 FALSE로 초기화되어 버립니다. 그러면 마우스 버튼을 눌렀을 때 이 값을 TRUE로 바꾸어도 그 사실을 기억하지 못하며 마우스 이동시 버튼을 눌렸다는 사실을 알지 못하므로 그리기를 하지 않게 됩니다. bNowDraw변수는 버튼을 누른 채로 이동중이라는 것을 기억하는 역할을 하므로 전역이거나 정적 변수여야 합니다.
WM_LBUTTONUP 내에 MoveToEx와 LineTo는 마지막 선을 완성하는 역할을 합니다. MOVE에서 ROP모드를 NOT으로 설정하여 기존 선을 반전시키며 중간과정을 그리는데 이 상태로 종료해 버리면 마지막 그린 선과 겹쳐진 다른 선은 지워져 버립니다. 그래서 버튼을 놓을 때 최종 선분을 한번 더 그려야 합니다. 이게 잘 이해가 안되면 선 하나 그려놓고 비스듬하게 다른 선을 하나 더 그려 보면서 동작을 잘 관찰해 보세요.

황금가물치 12월11일 11:42:33  

친절한 설명 감사합니다.


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