디시인사이드 갤러리

갤러리 이슈박스, 최근방문 갤러리

갤러리 본문 영역

[win32 팁] 클래스의 멤버 함수를 콜백함수로 사용하는 방법

prismatic갤로그로 이동합니다. 2009.07.23 02:15:59
조회 157 추천 0 댓글 2

이라는 떡밥을 도대체 얼마나 질질 끌고 있는지 잘 모르겠다능...... 여튼 밤에 할일도 없고 해서 적어봄.

클래스에 HWND 박아놓고 멤버함수를 콜백으로 쓰고싶은 사람의 경우 도움이 될 듯



1. 콜백으로 쓸 멤버함수를 정적으로 선언.

가장 많이 쓰는 방법이지 싶은데...... 생성할 윈도우가 단 하나라면(혹은 생성할 윈도우가 모두 같은 콜백을 써도 된다면)

이 방법이 가장 무난하면서 쉬운 방법. 방법은 다음과 같다능.

class Foo {
public:
    HWND m_hWnd;
    static Foo *thisPointer;
    static LRESULT CALLBACK StaticWndProc(HWND, UINT, WPARAM, LPARAM);
    LRESULT WndProc(UINT, WPARAM, LPARAM);
};

Foo *Foo::thisPointer = NULL;

이렇게 대충 짠 다음에 CreateWindow 명령에서 lpVoid 인자에 this 포인터를 주면 WM_CREATE 메세지가 들어왔을 때

CREATESTRUCT의 lpParam 인자에 this 포인터가 들어있다능. 이걸 thisPointer에 주고 이후 처리는 저장된 요 포인터를 통해 처리.

LRESULT Foo::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if(WM_CREATE == uMsg) thisPointer = (Foo *)(((CREATESTRUCT *)lParam)->lpParam);

    return (thisPointer ? thisPointer->WndProc(uMsg, wParam, lParam : ::DefWindowProc(hWnd, uMsg, wParam, lParam));
}

대충 이런식으로 코드가 나옮. 근데 이 방법은 당연하게도 창을 딱 하나만 처리할 수 있게 됨. 따라서 메인 클라이언트가 하나인 경우인

게임이라던가 등에는 유용하게 사용할 수 있으나 역시 불안정한 방법.



2. 여분 메모리 사용

윈도우 클래스 등록할 때 윈도우 여분 메모리를 두고 거기다가 포인터를 쳐박는 방법. 핸들이랑 클래스 포인터가 연동되므로 그나마 안정적이긴 한데

그래도 문제는 발생. 하면 할 수록 문제를 발견하게 되긴 함. 여튼 방법은 매우 많음. 근데 WM_CREATE 인자에 딸려오는 lParam을 살리기 위해 나는

저번에 질문할 때 간간히 올렸던 코드를 사용하고 있다능 ㅠㅜ 허접코드 같으니라구

먼저 가장 먼저 콜백함수로 사용할 정적 함수 1을 선언. 이 녀석은 WM_CREATE 메세지가 들어오는 그 순간

전해지는 this 포인터를 받아 사전처리를 해 주고 다음 콜백함수로 서브클래싱을 해 줌.

서브클래싱 될 콜백함수인 정적 함수 2는 핸들의 여분메모리에서 포인터를 뽑아 실제 실행될 멤버함수를 사용하게 하는 역할. 이 때 실제 실행될

멤버함수는 상속을 고려해서 virtual로 선언해 주는 것이 좋음.

코드는 대충 이런 식이 될 거라능...

class Foo {
public:
    HWND m_hWnd;
    static LRESULT CALLBACK StaticWndProc1(HWND, UINT, WPARAM, LPARAM);
    static LRESULT CALLBACK StaticWndProc2(HWND, UINT, WPARAM, LPARAM);
    virtual LRESULT WndProc(UINT, WPARAM, LPARAM);
};

물론 윈도우 클래스를 등록할 때 여분 메모리는 4바이트 챙겨뒀다고 가정.

이제 StaticWndProc1을 짜야댐. 근데 사실 CreateWindow를 호출하면 WM_CREATE이 가장 먼저 오는 게 아님. 그 전에 이상한 메세지들이 오는데

얘들은 ::DefWindowProc 함수로 처리해 줘야댐. 안그러면 창이 마치 WS_POPUP처럼 생성된다능.

그리고 한가지 더 유의할 점은, 아마 CreateWindow를 생성할 때 m_hWnd = CreateWindow(); 뭐 대충 이런식으로 할 것인데

WM_CREATE가 오는 시점에서 m_hWnd에는 아무 값도 리턴되지 않는다능! 따라서 StaticWndProc1에서 미리 처리해 줘야 됨.

어차피 WM_CREATE의 시점에서 -1을 리턴해 주면 최종적으로 m_hWnd에는 NULL이 리턴되므로 미리 처리해 줘도 됨.

왜 미리 처리해 주냐면, WM_CREATE 시점에서 m_hWnd를 부모로 해서 컨트롤을 만들 경우 m_hWnd에는 이 시점에서 자신의 핸들이

들어가 있지 않다능...... 그래서 전에 파워양파링한테 낚였던 그 질문에서 피를 말렸었음.

LRESULT Foo::StaticWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    if(WM_CREATE == uMsg) {
        ((oHWND *)(((CREATESTRUCT *)lParam)->lpCreateParams))->m_hWnd = hWnd; // 미리 m_hWnd에 핸들을 줌

        ::SetWindowLongW(hWnd, 0, (long)(((CREATESTRUCT *)lParam)->lpCreateParams)); // 여분 메모리에 클래스 포인터를 줌
        if((long)(((CREATESTRUCT *)lParam)->lpCreateParams) != ::GetWindowLong(hWnd, 0)) return -1; // 확인해서 실패했다면 즐염 ^^


        ::SetWindowLong(hWnd, GWL_WNDPROC, (long)PreProc2); // 이번엔 프로시져를 서브클래싱
        if((long)PreProc2 != ::GetWindowLong(hWnd, GWL_WNDPROC)) return -1; // 실패했으면 즐 ^^

        return ::SendMessage(hWnd, uMsg, wParam, lParam); // 이미 서브클래싱 되었으니까 메세지를 보내버려서 리턴
    }


    return ::DefWindowProc(hWnd, uMsg, wParam, lParam); // 그 이전의 메세지들은 다 이걸로 처리
}

뒤의 서브클래싱을 굳이 할 필요 없이 그냥 if문을 써도 되지 않을까? 라고 한다면, 물론 가능. 다만 몇 개의 변수가 추가되거나 하겠음.

예를 들자면 bool bCorrect라는 멤버변수를 두고 false로 초기화 한 후 WM_CREATE가 들어오면 bCorrect를 true로 바꾼 뒤

마지막에서 bCorrect가 false면 ::Def...를 부르고 아니면 여분 메모리에 저장시킨 포인터를 다시 불러와서 그걸로 작동해도 되는데

if문이나 변수 하나가 더 붙는 거 빼고는 전혀 상관 없다능 ^^

그리고 StaticWndProc2에서 저장된 포인터를 통해 멤버함수를 호출해 리턴한다능

LRESULT Foo::StaticWndProc2(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return ((Foo *)GetWindowLong(hWnd, 0))->WndProc(uMsg, wParam, lParam);
}

이렇게 해 두면 Foo를 상속하면서 WndProc를 오버라이드한 클래스라 하더라도 문제없이 잘 돌아갈 거라능.



뿡뿡.

추천 비추천

0

고정닉 0

0

댓글 영역

전체 댓글 0
등록순정렬 기준선택
본문 보기

하단 갤러리 리스트 영역

왼쪽 컨텐츠 영역

갤러리 리스트 영역

갤러리 리스트
번호 제목 글쓴이 작성일 조회 추천
설문 어떤 상황이 닥쳐도 지갑 절대 안 열 것 같은 스타는? 운영자 24/05/20 - -
147210 그런데, 윤쿰횽은 그만둔거야? [2] Vita500갤로그로 이동합니다. 09.09.10 76 0
147209 프로그래밍 금액 질문.. (답변 좀 굽신굽신) [14] 소대갤로그로 이동합니다. 09.09.10 155 0
147207 나 여친이랑 여행가기로 했음 [4] ㅇㅇㅃ갤로그로 이동합니다. 09.09.10 124 0
147206 아오 근데 왜 내 여친님은 항상 참치갤로그로 이동합니다. 09.09.10 67 0
147205 windows fopen 질문. [21] 물속의다이아갤로그로 이동합니다. 09.09.10 181 0
147204 'ㅅ' prismatic갤로그로 이동합니다. 09.09.10 45 0
147202 프로그래밍 좀 못하는데 프로그래밍에 취업해도 괜찮을련지.. [14] 목소리(121.174) 09.09.10 246 0
147201 이런거 보면 정말 열받아 [6] 이모군(110.8) 09.09.10 116 0
147200 내가 보기에 결국 중요한건 자본이다. [9] yundream(211.189) 09.09.10 142 0
147199 난 C언어 백만줄 발로 코딩한다... [3] 물속의다이아갤로그로 이동합니다. 09.09.10 144 0
147198 난 C언어 2000줄 코딩 발로 한다. [8] 물속의다이아갤로그로 이동합니다. 09.09.10 148 0
147196 아프리카 여행 [8] 유리한갤로그로 이동합니다. 09.09.10 120 0
147194 난 다부서 마음에 드는데? [1] 유리한갤로그로 이동합니다. 09.09.10 80 0
147193 디시에 그런말이 있냐능? [2] Vita500갤로그로 이동합니다. 09.09.10 68 0
147191 형들 여행갈건데. [25] yundream(211.189) 09.09.10 170 0
147190 박재범 피장파장이네요 [11] 이모군(110.8) 09.09.10 161 0
147189 솔직히 C언어 좆밥도 2천줄 코딩한다. [22] 다부서(211.227) 09.09.10 298 0
147187 수업시간에 입갤. [1] 혼아갤로그로 이동합니다. 09.09.10 42 0
147186 내가 집에서 RAID 0인가 그걸 쓰거든 [6] nRST(114.206) 09.09.10 88 0
147185 내가 보기엔 자본보다는 지식이 더 중요한 factor 같은데... [7] 분당살람갤로그로 이동합니다. 09.09.10 83 0
147184 지금 C가 중요한게아냐!! API 고수 없엉? [10] 다부서(211.227) 09.09.10 128 0
147183 ccna 자격증 취득쉽나여? [2] 사성천갤로그로 이동합니다. 09.09.10 77 0
147181 저도 리눅스를 깔기로 했습니다. [14] prismatic갤로그로 이동합니다. 09.09.10 136 0
147180 야근 개발자의 애환 [5] LightEach갤로그로 이동합니다. 09.09.10 137 0
147179 C언어를 배워보려고 책사서 보고있는데 첨부터 막히네요 -_- [3] 반반쓰갤로그로 이동합니다. 09.09.10 79 0
147178 씨언어 도움을주실 횽잇나요 . ~ 모가 틀린거지요.... [3] dd(211.114) 09.09.10 63 0
147176 자본가와 노동자라.. [8] ㄱㄱ(211.254) 09.09.10 98 0
147174 호기심에 한 번 구입해본 SSD .. [9] 때릴꺼야?(116.40) 09.09.10 130 0
147172 우리는 자신의 후장에 대해 조금 더 신중 할 필요가 있다. [3] 개쉛기갤로그로 이동합니다. 09.09.10 89 0
147171 오브젝트 풀이란걸 만드는데.. [18] Vita500갤로그로 이동합니다. 09.09.10 94 0
147170 [input = file] [4] 하이애나갤로그로 이동합니다. 09.09.10 82 0
147169 횽님들 액션스크립트 요거 하나만 가르쳐주시면 프갤을 떠날게요;; [7] 위위(124.61) 09.09.10 80 0
147167 아오!! 캡쳐도 막아놓고 가상프린트 인쇄도 안되고 미치겠네 [4] MC손오공갤로그로 이동합니다. 09.09.10 106 0
147165 형들좀 도와줘. 프린터스크린 기능도 막아놨어 [7] MC손오공갤로그로 이동합니다. 09.09.10 153 0
147164 강컴추천인 아이디 써주면 뭐 좋은거있듬? [3] 개쉛기갤로그로 이동합니다. 09.09.10 77 0
147163 신발라마 보세염 ㅇㄴㅣㅏ갤로그로 이동합니다. 09.09.10 48 0
147162 아니. 온라인아냐. pdf실행창에서 프린트스크랩누르면 [3] MC손오공갤로그로 이동합니다. 09.09.10 112 0
147161 한장한장 캡쳐뜰려그랬는데. 프린터스크랩 기능도 막아놨어 [5] MC손오공갤로그로 이동합니다. 09.09.10 81 0
147160 션훃 저번에 저자서명 책받으려면 어찌하면될까염 'ㅅ' [7] 개쉛기갤로그로 이동합니다. 09.09.10 87 0
147159 신분제 사회이긴 한데. [7] yundream(211.189) 09.09.10 146 0
147158 10초뒤에 false값을 리턴하는 메소드를 만들려구 하는데... [5] 신발라마갤로그로 이동합니다. 09.09.10 77 0
147156 gromit 씨 파일한번만 풀어줘 소원이야 [2] MC손오공갤로그로 이동합니다. 09.09.10 50 0
147155 변듣보의 등장은 흥선대원군의 대외정책이 발단이다. [3] 개쉛기갤로그로 이동합니다. 09.09.10 78 0
147154 Sean을 뭐라고 읽을 것인가! [9] 그런데갤로그로 이동합니다. 09.09.10 125 0
147153 파일 업로드시 검사하기위해 [11] 하이애나갤로그로 이동합니다. 09.09.10 91 0
147152 성인들을 위한 게임 콘솔, SexBox 3600!? [3] 키즈라엘갤로그로 이동합니다. 09.09.10 136 0
147151 혹시 배치화일로 레지스트리 접근 가능? [3] 중달(121.166) 09.09.10 66 0
147149 그런건 알고 싶지도 않고. [4] yundream(211.189) 09.09.10 123 0
147148 내가 동서울 쪽에서 경기도 부천으로 이사를 했는데 컴이 엄청 빨라졌어. [5] rntjr갤로그로 이동합니다. 09.09.10 107 0
147147 변듣보는 관심받고 싶어서 일까? [8] 물속의다이아갤로그로 이동합니다. 09.09.10 108 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2