디시인사이드 갤러리

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

갤러리 본문 영역

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

prismatic갤로그로 이동합니다. 2009.07.23 02:15:59
조회 158 추천 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/27 - -
148011 이때쯤 올라오는 홈페이지 광고 [2] Vita500갤로그로 이동합니다. 09.09.16 61 0
148010 자바 인터페이스 질문 [1] 신발라마갤로그로 이동합니다. 09.09.16 58 0
148009 하이킹 다녀오기 전에 기운이 좀 업ㅂ었다능. [7] Tathagata갤로그로 이동합니다. 09.09.16 68 0
148008 아이팥 가격 전격적 인하 [8] Vita500갤로그로 이동합니다. 09.09.16 194 0
148006 [New] 병신 리스트 업데이트!! [4] LightEach갤로그로 이동합니다. 09.09.16 147 0
148005 DLL 디버깅 하려고 하는데, 브레이크 포인트가 안잡혀 ㅠㅜ [7] 초보플머(121.139) 09.09.16 107 0
148003 1인 창업 아이템 선정시 주의사항 [1] 분당살람갤로그로 이동합니다. 09.09.16 118 0
148002 CDMA는 우리나라에서 상용화 되었으므로 우리나라 기술임 [4] nRST갤로그로 이동합니다. 09.09.16 112 0
148001 우왕 뇌자알 택배 받았다 [5] ㅇㅇㅃ갤로그로 이동합니다. 09.09.16 115 0
148000 내가 졸라 궁금한게 있어서 그러는데 [5] jujubar9갤로그로 이동합니다. 09.09.16 92 0
147999 프갤 잉여 구출 프로그램은 망했다. [4] 백수플머(121.139) 09.09.16 108 0
147998 허세부리는 새퀴들 [11] 피로토스갤로그로 이동합니다. 09.09.16 226 0
147997 최초의 CPU가 일본에서 만들어졌다는건... [26] 좃프로글래머(124.53) 09.09.16 344 0
147996 진짜 좃프 왜이럼? [3] prismatic갤로그로 이동합니다. 09.09.16 99 0
147995 프갤횽들 뇌자알 어디서 구입하셨나요?? [3] 천회장(125.7) 09.09.16 75 0
147992 내가 타루를 좋아하게 된 이유중에 하나 [5] 유리한갤로그로 이동합니다. 09.09.16 173 0
147989 형님들 공유기 없이 포트포워딩이 될까요? [4] GGC갤로그로 이동합니다. 09.09.16 110 0
147988 아 시발 개쉚기, 좃프로그래머를 보니까 백수플머에 대한 감정이 눈녹듯한다 [3] 백수플머(121.139) 09.09.16 90 0
147987 사실 좃프횽 정도도 양반임 [17] Tathagata갤로그로 이동합니다. 09.09.16 148 0
147986 너님들 솔직히 말해봐. 나냐 좆프냐? [8] 개쉛기갤로그로 이동합니다. 09.09.16 140 0
147984 CPU의 시초가 일본이었다는건 [29] 좃프로글래머(124.53) 09.09.16 254 0
147983 C++ 까는 횽아들은 봅니다. [2] 물속의다이아갤로그로 이동합니다. 09.09.16 89 0
147981 뇌자알 저자님께 질문 있습니다 [5] INT 21H(211.215) 09.09.16 120 0
147980 학교에서 디씨질은 무리다 [1] prismatic갤로그로 이동합니다. 09.09.16 48 0
147979 언젠가 부터 디씨 갤러리 리프레시가 잘 동작이 안되는 것 같아. [2] DC플머(121.139) 09.09.16 74 0
147978 난 진짜 프갤로 간다 [2] nRST갤로그로 이동합니다. 09.09.16 70 0
147977 이번 방학 때 목표 [1] jujubar9갤로그로 이동합니다. 09.09.16 50 0
147975 문자열 다루기의 중요성은 아무리 강조해도 지나치지 않다. [2] 백수플머(121.139) 09.09.16 88 0
147974 다른 사람이 쓴 책을 까서는 안된다. [5] 개쉛기갤로그로 이동합니다. 09.09.16 113 0
147973 웹에서 프린트 제어... [1] 초보자갤로그로 이동합니다. 09.09.16 59 0
147972 아 시발 플머새끼를 보니까 오사카와 스미골에 대한 감정이 눈녹듯한다 [5] nRST갤로그로 이동합니다. 09.09.16 113 0
147971 초보플머들아, 매크로를 두려워하지 말거라. [2] 백수플머(121.139) 09.09.16 101 0
147969 한빛 편집장은 무슨 생각으로 표지를 저래놓거지? [6] nRST갤로그로 이동합니다. 09.09.16 119 0
147968 뉴비로서 포인터 배울 때 언제쓸가했더만 [4] jujubar9갤로그로 이동합니다. 09.09.16 88 0
147966 뇌자알 프갤러가 쓴거임? [6] jujubar9갤로그로 이동합니다. 09.09.16 196 0
147964 숙신님... [1] 강군님갤로그로 이동합니다. 09.09.16 33 0
147962 적분 횽님 감사합니당~~ 성대아싸(115.145) 09.09.16 34 0
147961 *nix 와 win 에서 소스 수정없이 돌아가는 서버 프로그램의 포스. [1] rntjr갤로그로 이동합니다. 09.09.16 117 0
147959 던파하는훃들 서버어디임?? 'ㅅ' [4] 개쉛기갤로그로 이동합니다. 09.09.16 59 0
147957 와, 영어가 쉬운듯 하면서도 어렵고, 간단한거 같으면서 복잡하네. [2] 머그컵갤로그로 이동합니다. 09.09.16 77 0
147954 비주얼 스튜디오 모르고 처음 시작할때 c++누를라다가 씨샵 눌렀는데 어떻 [6] 보지무(59.22) 09.09.16 96 0
147953 유리한 횽은 봅니다. [1] clique갤로그로 이동합니다. 09.09.16 72 0
147951 하루를 마감하는 음악 ㅇㅇㅃ갤로그로 이동합니다. 09.09.16 47 0
147950 님들아 아직도 버츄어박스 씀? 왜 위대한 마소님을 안믿음? [4] 씬입사원갤로그로 이동합니다. 09.09.16 119 0
147949 가만보니까 티스토리 할려면요 굽신대야 하근여 [4] 성대아싸(121.137) 09.09.16 94 0
147947 그런관계로 Rei@디씨갤로그로 이동합니다. 09.09.16 39 0
147946 3차원 배열을 동적할당했는데 왜 엑세스 오류가 뜨나염.. 한수좀 굽신 [8] sdf(116.122) 09.09.16 74 0
147945 아이폰 대항마로 나온 M1000폰 [8] 씬입사원갤로그로 이동합니다. 09.09.16 177 0
147944 진짜 프갤문을 여는 음악 [7] 부락페스티발갤로그로 이동합니다. 09.09.16 70 0
147943 닫힌 프갤문을 다시 여는 음악 [3] Rei@디씨갤로그로 이동합니다. 09.09.16 51 0
갤러리 내부 검색
제목+내용게시물 정렬 옵션

오른쪽 컨텐츠 영역

실시간 베스트

1/8

뉴스

디시미디어

디시이슈

1/2