디시인사이드 갤러리

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

갤러리 본문 영역

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

prismatic갤로그로 이동합니다. 2009.07.23 02:15:59
조회 159 추천 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 - -
152235 현실이 이러네 [2] 이모군(116.127) 09.10.13 74 0
152233 아 프로그래머들 존나 개새끼네 ㅇㅇ [21] ㅇㅇ(211.55) 09.10.13 356 0
152232 ㅇㅇ 안녕 프로그래머 게이형들 질문좀요 ㅇㅇ [7] ㅇㅇ(211.55) 09.10.13 144 0
152231 횽들 내가 swap 어딧는지는 찾앗거든;; [2] 미믹(115.161) 09.10.13 77 0
152230 ARM에대해서 질문 몇개만요... [13] ㅇㄴㅁㅇㅇ(210.93) 09.10.13 148 0
152229 내가. . 멀 잘 못했지.. 오류쫌.. 잡아주셔요 [9] 학!(165.229) 09.10.13 567 0
152228 암프로세서에서 ISA 가 구체적으로 먼가염? [5] ㅁㄴㅇ(210.93) 09.10.13 102 0
152225 혹시 회사에서 헤드셑 쓰고 있다가... [7] 물속의다이아갤로그로 이동합니다. 09.10.13 170 0
152224 우이씨.. 어제 힘들게 해서 레포트 냈는데. [3] IHF갤로그로 이동합니다. 09.10.13 140 0
152223 졸업 예정중인 취업 준비생인 횽들은 보아라... [2] 물속의다이아갤로그로 이동합니다. 09.10.13 181 0
152220 어떤 근무 환경이 더 정상적임 ?? [8] 미츠도모에갤로그로 이동합니다. 09.10.13 183 0
152217 원자력 배터리....ㅎㄷㄷ [5] 임베디드(112.150) 09.10.13 215 0
152215 횽들 자바에서 스왑함수 어디에 들어잇어? [7] 미믹(115.161) 09.10.13 127 0
152212 [늅늅] 한글로안나오고 일본어로나와요 [3] 발랑갤로그로 이동합니다. 09.10.13 122 0
152211 진정한 일본식 변태 코드 [6] 물속의다이아갤로그로 이동합니다. 09.10.13 281 0
152210 쿼리를 조금 다루다 보니깐 손발이 편하네 진짜... [1] 캐꼬꼬닭(112.216) 09.10.13 112 0
152209 여캐한테 선물한다고 꼭 여친이라는 법은 없다능 [6] 개쉛기갤로그로 이동합니다. 09.10.13 152 0
152208 아주아슬님만봐여 [7] (59.30) 09.10.13 106 0
152207 api입문하는데 진짜 쉬운거 한개만 도와줘 늅늅 [1] 이쁜뇌종양갤로그로 이동합니다. 09.10.13 114 0
152206 혹시 스피너님 123쪽 숙제하시는건가여?? [2] 12(59.30) 09.10.13 82 0
152205 아 질문하러 왔는데 아랫놈이 나랑 질문이 비슷해 [6] 스피너(119.206) 09.10.13 118 0
152204 쉬운 문제 하나만 풀어주세요 [13] 12(59.30) 09.10.13 147 0
152203 윈도우7 런칭 파티 가는 사람 있음? [4] shunman(220.69) 09.10.13 110 0
152201 여자애한테 선물하나하려고 [6] 개쉛기갤로그로 이동합니다. 09.10.13 155 0
152199 VS 2008 공동 작업하시는 분들에게 질문드림미다. [1] ㅇㄴㅣㅏ갤로그로 이동합니다. 09.10.13 77 0
152198 아직도 대학교에는 부정부패가 존재한다. [3] jujubar9갤로그로 이동합니다. 09.10.13 141 0
152196 고액연봉자에 대한 관점의 문제 [10] 그런데갤로그로 이동합니다. 09.10.13 293 0
152195 취직하면 여자친구한테 젤 먼저 사주고 싶은거 [5] 임베디드(112.150) 09.10.13 213 0
152193 교수 후장 빠는 애들은 대체 왜 빠나여? [11] ㅇㅇ(121.130) 09.10.13 262 0
152192 주가 실시간 정보 데이터 관련 질문.. [21] 캐꼬꼬닭(112.216) 09.10.13 222 0
152191 미국 10대 연봉킹 [2] ㅇㅇㅇ(64.148) 09.10.13 224 0
152190 난 한 5년뒤에나 결혼식 올릴 수있겠다 .. [8] Pupustory갤로그로 이동합니다. 09.10.13 157 0
152189 회사 모과장님의 말씀 [2] 아긍대장갤로그로 이동합니다. 09.10.13 157 0
152188 ip주소 알아내는 법. [3] 빕뱟뱟갤로그로 이동합니다. 09.10.13 190 0
152187 4인 플젝(대학)을 혼자 다 해서 냈지만 성적은 내가 제일 안 나옴 [5] 아앙(211.243) 09.10.13 165 0
152186 winpcap으로 네트웍 latency 를 줄일수 있나요 [3] (218.149) 09.10.13 82 0
152184 내 덕질인생중에 이런 작품 처음이다... [15] JuEUS-U갤로그로 이동합니다. 09.10.13 281 0
152183 형들 정중하게 부탁하나만드릴께여 고정닉 IP 쉽게알수는없나요? [10] 리스(121.164) 09.10.13 219 0
152182 횽들, LPC 2000 시뮬이 안되요.... [3] 전미선(121.139) 09.10.13 74 0
152181 학생과 교수와의 관계 [7] 개쉛기갤로그로 이동합니다. 09.10.13 230 0
152180 안녕하세요 DC 첫 인사드립니다. [12] 미애남편갤로그로 이동합니다. 09.10.13 197 0
152179 마누라 몰래 [3] 유리한갤로그로 이동합니다. 09.10.13 154 0
152177 이런 시 [3] 유리한갤로그로 이동합니다. 09.10.13 89 0
152176 마누라에게 들켰다 --- DSLR 버전 찾았다능... [2] 아주아슬갤로그로 이동합니다. 09.10.13 186 0
152175 망할 교수.. [1] ㅁㄴㅇㄹㄴㅁㄷ(119.64) 09.10.13 69 0
152174 왜 울나라 IT기업은 법률문제에 무지한지 모르겠다. [7] 구루구루(115.145) 09.10.13 152 0
152172 사직서. [2] Gromit갤로그로 이동합니다. 09.10.13 141 0
152171 갑과 을과의 관계... [4] 물속의다이아갤로그로 이동합니다. 09.10.13 97 0
152170 나아가 학교와 학생의 관계 [9] ms(76.64) 09.10.13 125 0
152169 교수와 학생과의 관계 [3] 학생(125.128) 09.10.13 139 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2