핸들이란?
- 윈도우(OS)에서 각 객체에 부여한 고유한 번호(정수)
Create...
을 통해 만드는 객체에 보통 할당된다
#include <stdio.h>
#include <Windows.h>
#include <tchar.h>
int main()
{
// 메모장의 핸들을 받는다.
HWND hwnd = FindWindow(0, _T("제목 없음 - 메모장"));
printf("%d\n", hwnd);
// 특정 포인트에 있는 윈도우의 핸들을 받는다.
POINT pt = {10, 10};
HWND hwnd2 = WindowFromPoint(pt);
// 메모장을 다른 프로세스에서 컨트롤할 수 있다.
getchar(); MoveWindow(hwnd, 0, 0, 300, 300, TRUE);
getchar(); ShowWindow(hwnd, SW_HIDE);
getchar(); ShowWindow(hwnd, SW_SHOW);
// 단, 다른 스레드에서 사용된 DestroyWindow는 해당 hwnd을 종료하지 못함
DestroyWindow(hwnd);
TCHAR name[256];
GetClassName(hwnd, name, 256); // 클래스 이름을 받을 수 있다.
//printf("%s\n", name); // 유니코드 주의
_tprintf(_T("%s\n"), name);
}
핸들 타입의 정체
핸들은 어떻게 구현이 되어있을까? 아래처럼 단순히 struct로 구현되어있나
typedef int HWND;
typedef int HICON;
void MoveWindow(HWND hwnd, int x, int y)
{
}
HICON CreateIcon // ...
int main()
{
HICON hIcon = CreateIcon();
MoveWindow(hIcon, 10, 10);
// 단순히 struct로 구현시
// HWND를 넣어야하는데 HICON을 넣어도 정상적으로 빌드가 된다.
// 타입의 안정성 문제가 있다
}
핸들이 단순 int를 typedef할 경우 HWND, HICON … 어떤게 들어갈지 알 수 없다.
해결책?
struct HWND__
{};
typedef struct HWND__* HWND;
struct HICON__
{};
typedef struct HICON__* HICON;
// 다른 구조체의 포인터에 암시적 형변환이 불가능
// 포인터기에 정수가 들어갈 수 있음
// 해결!
- 모든 핸들 타입은 구조체의 포인터
- 구조체 자체는 사용하지 안는다.
- 다른 구조체 포인터 타입은 암시적 형 변환이 되지 않는다.
// 단, HANDLE은 모든 핸들을 담을 수 있는데 void*이기 때문이다.
typedef void* HANDLE;
윈도우 Object와 윈도우 스타일
CreateWindowEx()
를 하면 윈도우 정보(x, y, width, height …)이 Window Object(윈도우 객체)화 되어 어딘가 저장된다.- 저장된 Window Object는
ShowWindow()
를 통해서 화면에 그려진다. - Window Object에 접근(메모리접근) 할 방법은 Device Driver 정도를 통해서 접근이 가능하다(하지만 위험하고 어려움)
- 단, 옵션(스타일) 정도는 변경이 가능하다.(
GetWindowLongPtr
,SetWindowLongPtr
)
int _tmain()
{
HWND hwnd = FindWindow(_T("Notepad"), 0);
getchar();
LONG style = GetWindowLongPtr(hwnd, GWL_STYLE);
style = style & ~WS_CAPTION;
SetWindowLongPtr(hwnd, GWL_STYLE, style);
// SetWindowLongPtr호출 후에는 SetWindowPos를 호출해야한다.(Window10 이전버전 기준)
SetWindowPos(hwnd, 0, 0, 0, 0, 0, SWP_NOZORDER | SWP_NOMOVE | SWP_NOSIZE | SWP_DRAWFRAME);
}
윈도우 메세지
LRESULT __stdcall WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// ...
}
- WPARAM(WORD PARAMETER) : 16비트 시절에 WORD(16bit)라서 WPARAM이라 불림, 지금은 32bit정수임
- LPARAM(LONG PARAMETER) : 말 그대로 LONG(32bit)
메시지를 보내는 방법 2가지
PostMessage
: 메시지를 메시지 큐에 넣고 즉시 반환SendMessage
: 메시지를 메시지 큐에 넣고 처리가 완료 될 때까지 대기
다른 프로세스의 윈도우 종료
SendMessage(hwnd, WM_CLOSE, 0, 0);
사용자 정의 메시지
#define WM_MYMESSAGE WM_APP+100
int _tmain()
{
HWND hwnd = FindWind(0, _T("Hello"));
getchar();
SendMessage(hwnd, WM_MYMESSAGE, 0, 0);
}