언리쉬드 조경민 98.6.23
===================================

제 9장

윈도우 다이얼로그 박스 컨트롤


윈도우 쿨랴스______________________________________

모든 윈도우는 윈도우 클래스와 결합한다. 윈도우 클래스는 윈도우

운영체제가 제공하거나 사용자가 RegisterClass함수를 통해 등록한

클래스이다.윈도우 클래스의 목적은 관련된 윈도우의 특성과 행동을

정의하는 것이다. 윈도우 행동은 프로시저의 분기문에 의해서 이루어진다.

윈도우 프로시저는 메세지가 SendMessage함수를 통해 윈도우로 보내지거나

포스트된 메세지가 DispatchMessage함수를 통해 디스패치 될때 마다

호출된다. 원하지 않는 메세지는 디폴트 윈도우 프로시저

(DefWindowproc또는 다이얼로그 박스인경우는 DefDlgProc)에서 처리한다.

[*]___________________________________________________

서브클래싱(Subclassing)

서브클래싱은 윈도우 프로시저를 가진 윈도우 클래스를 다른 윈도우

프로시저로 바꾸는 것을 의미한다. 이것은 SetWindowLong이나 SetClassLong

함수를 호출함으로써 이루어진다.

GWL_WNDPROC 인덱스 값으로 SetWindowLong을 호출하면 특정 윈도우를 윈도우

프로시저로 대체한다. 반대로 GCL_WNDPROC 인덱스 값으로 SetWindowLong을 호출

하면 SetClassLong을 호출하여 생성된 그 클래스의 모든 윈도우를 윈도우 프로시

저로 대체한다.

BUTTON에 대한 서브클래싱 예제 (버튼객체 하나에대한 행동 바꾸기)
컴파일 cl button.c user32.lib
```````--------------------------------------------------------
#include <windows.h>

WNDPROC OldWndProc;

LRESULT CALLBACK WndProc(HWND hwnd,UINT uMsg, WPARAM wParam,LPARAM lParam)
{
        switch(uMsg)
        {
        case WM_LBUTTONUP:
                DestroyWindow(hwnd);
                break;
        case WM_DESTROY:
                PostQuitMessage(0);
                break;
        default:
                return CallWindowProc(OldWndProc,hwnd,uMsg,wParam,lParam);
        }

        return 0;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE d2, LPSTR d3,int d4)
{
        MSG msg;
        HWND hwnd;

        hwnd = CreateWindow("BUTTON","Hello",WS_VISIBLE | BS_CENTER,100,100
                100,80,NULL,NULL,hInstance,NULL);

        OldWndProc = (WNDPROC)SetWindowLong(hwnd,GWL_WNDPROC,(LONG)WndProc);
        
        while(GetMessage(&msg,NULL,0,0))
                DispatchMessage(&msg);

        return msg.wParam;
}



BUTTON 클래스를 서브클래싱하기 (버튼 객체 전체에 대한-한응용프로그램에서- 행동바꾸기)
컴파일 cl button.c user32.lib
```````---------------------------------------------------------------------
#include <windows.h>

WNDPROC OldWndProc;

LRESULT CALLBACK WndProc(HWND hwnd,UINT uMsg, WPARAM wParam,LPARAM lParam)
{
        switch(uMsg)
        {
        case WM_LBUTTONDONW:
                MessageBeep(0xFFFFFFFF);
                break;
        default:
                return CallWindowProc(OldWndProc,hwnd,uMsg,wParam,lParam);
        }

        return 0;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE d2, LPSTR d3,int d4)
{
        MSG msg;
        HWND hwnd;

        hwnd = CreateWindow("BUTTON","Hello",WS_VISIBLE | BS_CENTER,100,100
                100,80,NULL,NULL,hInstance,NULL);

        OldWndProc = (WNDPROC)SetClassLong(hwnd,GCL_WNDPROC,(LONG)WndProc);
        
        DestroyWindow(hwnd);
        MessageBox(NULL,"Hello World","",MB_OK);
}

버튼 객체는 CreateWindow후 생겼다가 SetClassLong을 호출함과 직후 버튼 컨트롤 객체는

사라지게 된다. 그러나 SetClassLong에 의해서 이제부터 나오는 모든 버튼 객체의 행동이

바뀌게 되었다. 그래서 메세지 박스의 OK버튼을 누르게 되면 삑삑 소리가 나게 된다.


전역 서브클래싱

윈도우 시스템 전반에 걸친 행동을 바꾸기 위해서 사용된다. (3D 컨트롤  라이브러리

CTL3D.DLL이 구현된 방식이다.)16비트에서는 클래스를 서브클래싱하면 다른 응용프로그램

에서도 행동이 바뀌게 되었지만 Win32에서는 더이상 그렇지 않고 응용프로그램하나에서

끝나게 된다. 그렇게 하기 위해서는 DLL을 사용해서 모든 응용프로그램의 주소 공간에

DLL이 로드되는 것을 보장해야 한다는 것이다.

DLL을 만들었다면 윈도우NT에서는 래지스트리에 세팅을 만들어진다.

\HKEY_LOCAL_MACHINE\Software\Microsoft\WindowsNT\CurentVersion\Windows\APPINIT_DLLS

이 래지스트리 키 아래에 리스트된 DLL들은 새로 생성된 모든 프로세스의 주소 공간에

로드된다. 새로 몇개의 DLL을 추가하고자 한다면 패스네임과 스페이스로 분리하면 된다.

그러나 이방법으로는 윈95에서는 돌아가지 않는다.

DLL에서 서브클래싱 하기
컴파일 cl /lD button.c user32.lib
```~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#include <windows.h>

WNDPROC OldWndProc;

LRESULT CALLBACK WndProc(HWND hwnd,UINT uMsg, WPARAM wParam,LPARAM lParam)
{
        switch(uMsg)
        {
        case WM_LBUTTONDONW:
                MessageBeep(0xFFFFFFFF);
                break;
        default:
                return CallWindowProc(OldWndProc,hwnd,uMsg,wParam,lParam);
        }

        return 0;
}

BOOL WINAPI DllMain(HANDLE hModule,DWORD dwResson,LPVOID lpReserved)
{
        HWND hwnd;

        stich(dwResson)
        {
        case DLL_REOCESS_ATTACH:
                hwnd = CreateWindow("BUTTON","",0,0,0,0,NULL,NULL,hModule,NULL);
                OldWndProc = (WNDPROC)SetClassLong(hwnd,GCL_WNDPROC,(LONG)WndProc);
                DestroyWindow(hwnd);        
                
        }
        return TRUE;
}

이런 방법으로 명시된 DLL이 모든 응용프로그램 또는 더 상세히 말하자면 USER32.DLL와

연결된 모든 GUI응용프로그램의 주소 공간으로 로드 될수 있다는 것이다. 당신의 DLL에

아주 조금의 버그가 있더라도 전체 시스템의 안정성에 심각한 영향을 줄수 있다.

다행스럽게 DLL을 다른 프로세스의 주소 공간에 주입할수 있게 해 주는 방법이 있다.

첫번째 방법은 윈도우 후크 함수를 사용하는 것이다. SetWindowHookEx 함수를 사용하면

다른 응용프로그램의 주소 공간에 설치할수 있다. 이 메커니즘을 통해다른 프로그램이

소유한  윈도우 클래스에 새 윈도우 함수를 추가 할수 있다.

두번째 방법은 CreateRemoteThread함수를 이용하는 것이다. 이함수는 다른 프로세스의

컨텍스트에서 동작하는 스레드를 생성하는 기능이 있다.


수퍼클래싱(Superclassing)

수퍼클래싱은 기존의 클래스의 행동에 기반하여 새 클래스를 생성하는 것을 의미한다.

기존의 클래스를 수퍼클래싱하고자 하는 응용프로그램은 그 클래스를 설명하는

WNDCLASS 구조체를 얻기 위해 GetClasInfo 함수를 이용할수 있다. 이 구조체는 적당히

변경된 후에 새 클래스를 등록하는 RegisterClass함수를 호출하는데 쓰인다.


BUTTON 클래스를 수퍼 클래싱하기

#include <windows.h>

WNDPROC OldWndProc;

LRESULT CALLBACK WndProc(HWND hwnd,UINT uMsg, WPARAM wParam,LPARAM lParam)
{
        switch(uMsg)
        {
        case WM_LBUTTONUP:
                DestroyWindow(hwnd);
                break;
        case WM_DESTROY:
                PostQuitMessage(0);
                break;
        default:
                return CallWindowProc(OldWndProc,hwnd,uMsg,wParam,lParam);
        }

        return 0;
}

int WINAPI WinMain(HINSTANCE hInstance,HINSTANCE d2, LPSTR d3,int d4)
{
        MSG msg;
        HWND hwnd;
        WNDCLASS wndclass;

        GetClassInfo(Hinstance,"BUTTON",&wndclass);
        wndclass.hInstance = hInstance;
        wndclass.lpszClassName = "NEWBUTTON";
        OldWndProc = wndclass.lpfnWndProc;
        wndclass.lpfnWndProc = WndProc;
        RegisterClass(&wndclass);
                
        hwnd = CreateWindow("NEWBUTTON","Hello",WS_VISIBLE | BS_CENTER,100,100
                100,80,NULL,NULL,hInstance,NULL);
        
        while(GetMessage(&msg,NULL,0,0))
        {
                if(msg.message == WM_LBUTTONUP)
                {
                        DestoryWindow(hwnd);
                        PostQuitmessage(0);
                }
                DispatchMessage(&msg);
        }

        return msg.wParam;
}

'KB > MFC/Win32' 카테고리의 다른 글

[개요] 윈도우프로그래밍  (0) 2004.03.19
윈도우프로그래밍 간략설명  (0) 2004.03.19
Unleashed Visual C++ 5.0 ????  (0) 2004.03.19
[db] sql  (0) 2004.03.19
[db] ODBC 파일 등록하기  (0) 2004.03.19

+ Recent posts