디시인사이드 갤러리

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

갤러리 본문 영역

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

prismatic갤로그로 이동합니다. 2009.07.23 02:15:59
조회 160 추천 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/06/10 - -
이슈 [디시人터뷰] 웃는 모습이 예쁜 누나, 아나운서 김나정 운영자 24/06/11 - -
152457 닥눈삼 3분하고 질문하면 까일지 모르겟지만... 메모리 변조... [1] 체다치즈(125.131) 09.10.15 73 0
152455 앱스토어에 프로그램 짤려면 어떤 언어를 배워야 돼? [4] 허무주의자갤로그로 이동합니다. 09.10.15 135 0
152454 뇌잘 왔음 [5] prismatic갤로그로 이동합니다. 09.10.15 100 0
152453 시간은 금이요. [7] yundream(211.189) 09.10.15 143 0
152452 이건 뭐하자는건지 ㅋㅋㅋ [9] rntjr갤로그로 이동합니다. 09.10.15 152 0
152451 안녕하세요. 늅늅 [4] 기름호랑이갤로그로 이동합니다. 09.10.15 95 0
152450 nProtect 가 표창을 받았답니다...... [5] 후시기바나(110.76) 09.10.15 188 0
152449 대학 다닐 때 이야기 하나... [3] 물속의다이아갤로그로 이동합니다. 09.10.15 101 0
152448 횽님들 봐주세욤,ㅠ [2] 살암살려,(203.250) 09.10.15 74 0
152447 XE사용하고 있는데 [1] Vita500갤로그로 이동합니다. 09.10.15 82 0
152445 학교 도서관은 도서 신청이 왜케 더디냐... [9] 혼아갤로그로 이동합니다. 09.10.15 95 0
152444 닥눈삼 여겼다고 욕먹을거같어!!!! 횽님들 알켜주세요;;; [12] 미애남편갤로그로 이동합니다. 09.10.15 128 0
152443 GPL 3.0 상업적으로 갖다쓰면 깜빵가나여?? [4] 아잉따잉갤로그로 이동합니다. 09.10.15 163 0
152442 횽들 개발 서적 좀 읽어? [12] 물속의다이아갤로그로 이동합니다. 09.10.15 211 0
152440 앜ㅋㅋㅋㅋ변듣봌ㅋㅋㅋㅋㅋㅋㅋㅋ [1] 유리한갤로그로 이동합니다. 09.10.15 103 0
152439 개쉛기횽을 위한 표절 짤방 [1] 아주아슬갤로그로 이동합니다. 09.10.15 103 0
152438 빵굽는 개발자. 간지좀 나냐? [7] 유리한갤로그로 이동합니다. 09.10.15 220 0
152437 회사 따돌림이라고 하긴 뭣하지만... [6] 아주아슬갤로그로 이동합니다. 09.10.15 188 0
152436 Resharper는 사랑이긴한데... ㅇㄴㅣㅏ갤로그로 이동합니다. 09.10.15 55 0
152434 지상 최대의 난적 [파일명검색] [8] 검색가(211.62) 09.10.15 145 0
152432 잉카 인터넷 표창 [5] Mr.Bation갤로그로 이동합니다. 09.10.15 134 0
152431 회사에도 따돌리고 그런거 있어여?? [8] ㅇㅇ(124.254) 09.10.15 147 0
152430 KT와이브로 에그 문의... [3] 물속의다이아갤로그로 이동합니다. 09.10.15 102 0
152429 일찍일어나는 새는 빨리 뒤진당. [4] yundream(211.189) 09.10.15 132 0
152428 아주쓸쓸횽을 위한 스페셜 짤방 [7] 개쉛기갤로그로 이동합니다. 09.10.15 140 0
152427 인터넷 개통 기념 -- 톰캣의 어원을 알아냈어! 아주아슬갤로그로 이동합니다. 09.10.15 149 0
152426 nhn도 멤버십 생겼네 [5] 빕뱟뱟갤로그로 이동합니다. 09.10.15 178 0
152425 잘못된 옛말 , '일찍 일어나는 새가 먹이를 쳐 얻는다' [4] 개쉛기갤로그로 이동합니다. 09.10.15 162 0
152424 여자애들은 왜이렇게 학점에 목숨거냐 [9] ㄹㄹ(121.157) 09.10.15 199 0
152423 디렉트엑스 10에서부터 멀티스레딩 ... [1] grunt갤로그로 이동합니다. 09.10.15 89 0
152422 흉들 내가 3d라이브러리 가지고 아이폰게임하나 만들라는데 [1] ㅡㅡ(116.36) 09.10.15 97 0
152419 쌈빡하게 포트란 질문. [2] 컴공볍진갤로그로 이동합니다. 09.10.15 74 0
152418 쉘스크립트로 만든 웹서버 [3] JuEUS-U갤로그로 이동합니다. 09.10.15 158 0
152416 핫핫핫 귀여워 [1] 이모군(110.8) 09.10.15 109 0
152414 너님들힘내 편의점습격사건갤로그로 이동합니다. 09.10.15 66 0
152413 진짜 여긴 뭐하는 회사인지 모르겠네... [20] 임베디드(112.150) 09.10.15 307 0
152412 든데 여자교수는정말 ㄱ- [5] 빙글이갤로그로 이동합니다. 09.10.15 267 0
152409 알고리즘이 문제야.ㅠㅠ [10] ㅁㄴㅇㄹ(203.223) 09.10.15 133 0
152408 프갤오빠들 펑션기능있자나영;ㅅ;.. [15] 빙글이갤로그로 이동합니다. 09.10.15 239 0
152405 지금까지 프갤에 남아있는 신사숙녀여러분 ^^ [4] IHF갤로그로 이동합니다. 09.10.15 89 0
152404 미친 말라리아.. 켁큇갤로그로 이동합니다. 09.10.15 61 0
152403 하도 처잤더니 [4] algo갤로그로 이동합니다. 09.10.15 109 0
152398 형님들 도와주세요,ㅠㅠ 간단한거임,ㅎ [7] 제발,(124.216) 09.10.14 95 0
152396 혹시 녹음 할줄 아는횽 없어? ㅠㅠ [1] 전호섭(113.131) 09.10.14 63 0
152395 형들 포트란에서 질문이 있어... [1] 꼐임(210.216) 09.10.14 54 0
152394 리눅스 커널 스케줄링 좀 해본형들 봐줘.. [5] 형들미안(121.169) 09.10.14 105 0
152393 돌아다니다가 랜덤채팅 떡밥을 물었어. [1] IHF갤로그로 이동합니다. 09.10.14 96 0
152392 퇴갤을 알리는...형들, 잘자 [4] 숙신갤로그로 이동합니다. 09.10.14 55 0
152390 프갤 족보를 만드는건 어때.. [8] Vita500갤로그로 이동합니다. 09.10.14 194 0
152389 프갤 족보를 만드는건 어때.. [4] Pupustory갤로그로 이동합니다. 09.10.14 152 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2