No.004 - 03 自前ドッキング・ツールバー クラス化 (ドッキング・システム) |
| 自前ドッキング・ツールバーの作成はCのままではつらいので、少しC++に移行します。 |
| 以下ドッキングツールバーを一式クラス化して、メインウィンドウの負担を軽くしています。 DOCK_SYSクラス内でドッキング・フローティング処理を一括しています。 メインウィンドウはDOCK_SYSクラスをひとつ保持しておいてWM_NCACTIVATE と WM_SIZE で所定の処理をするだけです。 メインウィンドウ と ビューウィンドウ のプロシージャとかはソース下の方で C のままのカタチで残してあります。 |
|
![]() |
|
|
|
|
・ドッキングシステム |
|
| 前回のDOCK_STRUCT構造体を元にDOCK_SYSという特殊なクラスを作っています。 メインウィンドウはDOCK_SYSクラスをひとつ保持しておいて、ドッキング関連の処理をDOCK_SYSクラスに丸投げする仕組みです。 DOCK_SYSクラスはDOCK_CONTEXTクラスをひとつ持ちドラッグ中の処理はDOCK_CONTEXTクラス内でします。 |
|
![]() |
![]() |
![]() |
| docking_test_03.cpp |
#define _WIN32_IE 0x0501
#include <windows.h>
#include <commctrl.h>
TBBUTTON tool_bar_buttons[] = {
{ STD_FILENEW, 1, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ STD_FILEOPEN, 2, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ STD_FILESAVE, 3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0 },
{ STD_COPY, 4, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ STD_CUT, 5, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ STD_DELETE, 6, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0 },
{ VIEW_NEWFOLDER, 7, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ VIEW_PARENTFOLDER, 8, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
};
// ドック・コンテキスト・構造体
class DOCK_CONTEXT {
public:
HRGN m_apply_rgn, m_work_rgn, m_work_rgn2, m_last_rgn; // リージョン
HDC m_desk_hdc; // デスクトップDC
int m_now_dragging; // ドラッグ中なら==1 そうでないなら==0
SIZE m_drag_size; // ドラッグ中の矩形サイズ
POINT m_cursor_offset; // ドラッグ中の矩形位置のマウス位置との差分
HBRUSH m_desk_old_brush; // デスクトップDC・ブラシ
HBRUSH m_half_tone_brush; // ハーフトーン・ブラシ
DOCK_CONTEXT(); // コンストラクタ
~DOCK_CONTEXT(); // デストラクタ
void start_drag(HWND hwnd); // ドラッグ開始
void drag(); // ドラッグ中
void end_drag(); // ドラッグ終了
};
// ドッキング・ツールバー統括クラス
class DOCK_SYS {
public:
HWND m_main_frame, m_popup_frame, m_htool_bar, m_htool_bar_frame, m_hview, m_hdock_bar; // 各HWND
int m_now_nc_activing; // WM_NCACTIVATEフラグ WM_NCACTIVATEの多重再送を防ぐ
int m_floating_flag; // フローティング・フラグ 浮いてれば==1 そうでないなら==0
DOCK_CONTEXT m_dock_context; // ドック・コンテキスト・構造体
regist_winc(char *caption, HBRUSH hbr_bg, WNDPROC proc); // ウィンドウクラス登録
create(HWND main_hwnd, HWND child_view_hwnd); // 生成
void on_ncactivate(HWND hwnd, WPARAM wp); // WM_NCACTIVATE 処理
void do_dock(); // ドッキング実行
void do_float(int x, int y); // フローティング実行
void recalc_layout(); // 子ウィンドウ位置再計算
void tool_on_lbuttondown(HWND hwnd); // ツールバー・マウス左ボタン押下
void tool_on_lbuttonup(); // ツールバー・マウス左ボタン押上
void tool_on_mousemove(); // ツールバー・マウス移動
// ポップアップ・フレーム・プロシージャ
PopupProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
static LRESULT CALLBACK StaticPopupProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
// ツールバー・プロシージャ
ToolBarFrameProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
static LRESULT CALLBACK StaticToolBarFrameProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
} ;
// コンストラクタ
DOCK_CONTEXT::DOCK_CONTEXT(){
WORD gray_pattern[8];
HBITMAP gray_bitmap;
int i;
m_now_dragging=0;
// ハーフトーン・パレット生成
for (i=0;i<8;i++) gray_pattern[i] = (WORD)(0x5555 << (i & 1)); // 0x5555 は2bitで 01010101 01010101
gray_bitmap = CreateBitmap(8, 8, 1, 1, &gray_pattern);
if (gray_bitmap != NULL) {
m_half_tone_brush = ::CreatePatternBrush(gray_bitmap);
DeleteObject(gray_bitmap);
}
}
// デストラクタ
DOCK_CONTEXT::~DOCK_CONTEXT(){
DeleteObject(m_half_tone_brush); // ハーフトーン・パレット破棄
}
// ドラッグ開始
void DOCK_CONTEXT::start_drag(HWND hwnd){
HWND desk_hwnd;
RECT rc;
m_now_dragging=1;
SetCapture(hwnd);
// デスクトップDCを得る
desk_hwnd=GetDesktopWindow();
LockWindowUpdate(desk_hwnd);
m_desk_hdc= GetDCEx(desk_hwnd, NULL, DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
m_desk_old_brush=(HBRUSH)SelectObject(m_desk_hdc, m_half_tone_brush);
// ドラッグ・サイズとマウスとの座標差
GetWindowRect(hwnd, &rc);
m_drag_size.cx = rc.right-rc.left;
m_drag_size.cy = rc.bottom-rc.top;
GetCursorPos(&m_cursor_offset);
m_cursor_offset.x -= rc.left;
m_cursor_offset.y -= rc.top;
// リージョン生成
m_apply_rgn = CreateRectRgn(0, 0, 0, 0);
m_work_rgn = CreateRectRgn(0, 0, 0, 0);
m_work_rgn2 = CreateRectRgn(0, 0, 0, 0);
m_last_rgn = CreateRectRgn(0, 0, 0, 0);
}
// ドラッグ中
void DOCK_CONTEXT::drag(){
POINT po;
RECT rc;
GetCursorPos(&po);
po.x-=m_cursor_offset.x;
po.y-=m_cursor_offset.y;
SetRectRgn(m_work_rgn, po.x, po.y, po.x+m_drag_size.cx, po.y+m_drag_size.cy);
SetRectRgn(m_work_rgn2, po.x+4, po.y+4, po.x+m_drag_size.cx-4, po.y+m_drag_size.cy-4);
CombineRgn(m_apply_rgn, m_work_rgn, m_work_rgn2, RGN_XOR);
CombineRgn(m_work_rgn, m_apply_rgn, m_last_rgn, RGN_XOR);
// 反転による矩形描画
GetRgnBox(m_work_rgn, &rc);
SelectObject(m_desk_hdc, m_work_rgn);
PatBlt(m_desk_hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, PATINVERT);
// 最後に描画した部分保持(再反転して消去)
CombineRgn(m_last_rgn, m_apply_rgn, NULL, RGN_COPY);
}
// ドラッグ終了
void DOCK_CONTEXT::end_drag(){
RECT rc;
m_now_dragging=0;
ReleaseCapture();
// 最後に描画した部分を消去(再反転してるだけ)
GetRgnBox(m_apply_rgn, &rc);
SelectObject(m_desk_hdc, m_apply_rgn);
PatBlt(m_desk_hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, PATINVERT);
// リージョン破棄
DeleteObject(m_apply_rgn);
DeleteObject(m_work_rgn);
DeleteObject(m_work_rgn2);
DeleteObject(m_last_rgn);
// デスクトップDCを解放
LockWindowUpdate(NULL);
if (m_desk_hdc) ReleaseDC(GetDesktopWindow(), m_desk_hdc);
SelectObject(m_desk_hdc, m_desk_old_brush);
}
// ポップアップウィンドウ・プロシージャ(static版)
LRESULT CALLBACK DOCK_SYS::StaticPopupProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
DOCK_SYS *p_dock_sys =(DOCK_SYS*)GetWindowLong(hwnd, GWL_USERDATA);
if (!p_dock_sys && (msg==WM_NCCREATE || msg==WM_CREATE)){
p_dock_sys = (DOCK_SYS*)((LPCREATESTRUCT)lp)->lpCreateParams;
SetWindowLong(hwnd, GWL_USERDATA, (LONG)p_dock_sys);
}
if (p_dock_sys) return p_dock_sys->PopupProc(hwnd, msg, wp, lp);
return DefWindowProc(hwnd, msg, wp, lp);
}
// ポップアップウィンドウ・プロシージャ
DOCK_SYS::PopupProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
int res;
switch (msg) {
case WM_NCACTIVATE: // タイトルバーのアクティブ化・非アクティブ化
on_ncactivate(hwnd, wp);
break;
case WM_LBUTTONDOWN:
tool_on_lbuttondown(hwnd); // ドラッグ開始
break;
case WM_LBUTTONUP:
tool_on_lbuttonup(); // ドラッグ終了
break;
case WM_MOUSEMOVE:
tool_on_mousemove(); // マウス移動(ドラッグ中)
break;
case WM_NCHITTEST:
res=DefWindowProc(hwnd, msg, wp, lp);
if (res==HTCAPTION) return HTCLIENT;
return res;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
// ツールバーのフレームウィンドウ・プロシージャ(static版)
LRESULT CALLBACK DOCK_SYS::StaticToolBarFrameProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp){
DOCK_SYS *p_dock_sys =(DOCK_SYS*)GetWindowLong(hwnd, GWL_USERDATA);
if (!p_dock_sys && (msg==WM_NCCREATE || msg==WM_CREATE)){
p_dock_sys = (DOCK_SYS*)((LPCREATESTRUCT)lp)->lpCreateParams;
SetWindowLong(hwnd, GWL_USERDATA, (LONG)p_dock_sys);
}
if (p_dock_sys) return p_dock_sys->ToolBarFrameProc(hwnd, msg, wp, lp);
return DefWindowProc(hwnd, msg, wp, lp);
}
// ツールバーのフレームウィンドウ・プロシージャ
DOCK_SYS::ToolBarFrameProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
RECT rc, rc2;
HDC hdc;
PAINTSTRUCT ps;
switch (msg) {
case WM_CREATE:
InitCommonControls();
m_htool_bar = CreateToolbarEx( hwnd, WS_CHILD | WS_VISIBLE | TBSTYLE_AUTOSIZE, 0, 6,
(HINSTANCE)HINST_COMMCTRL, IDB_STD_SMALL_COLOR, tool_bar_buttons, 7, 0, 0, 0, 0, sizeof (TBBUTTON)
);
GetWindowRect(m_htool_bar, &rc);
SetWindowPos(hwnd, NULL, 0,0, rc.right-rc.left, rc.bottom-rc.top, SWP_NOMOVE);
break;
case WM_PAINT:
hdc = BeginPaint(hwnd , &ps);
GetClientRect(hwnd, &rc);
rc.left=0; rc.top=0; rc.bottom=1; FillRect(hdc, &rc, GetSysColorBrush(COLOR_BTNSHADOW));
rc.top++; rc.bottom++; FillRect(hdc, &rc, GetSysColorBrush(COLOR_BTNHILIGHT));
if (!m_floating_flag){
// グリッパー描画
GetClientRect(hwnd, &rc);
rc.left+=2; rc.right=rc.left+3;
rc.top+=1; rc.bottom-=2;
rc2.left=rc.left; rc2.top=rc.top;
rc2.right=rc.right-1; rc2.bottom=rc.top+1; FillRect(hdc, &rc2, GetSysColorBrush(COLOR_BTNHILIGHT));
rc2.right=rc.left+1; rc2.bottom=rc.bottom-1; FillRect(hdc, &rc2, GetSysColorBrush(COLOR_BTNHILIGHT));
rc2.left=rc.right; rc2.top=rc.top;
rc2.right=rc.right-1; rc2.bottom=rc.bottom; FillRect(hdc, &rc2, GetSysColorBrush(COLOR_BTNSHADOW));
rc2.left=rc.left; rc2.top=rc.bottom;
rc2.right=rc.right; rc2.bottom=rc.bottom-1; FillRect(hdc, &rc2, GetSysColorBrush(COLOR_BTNSHADOW));
}
EndPaint(hwnd , &ps);
break;
case WM_SIZE:
SendMessage(m_htool_bar, WM_SIZE, wp, lp); // ツーバーのリサイズ
if (!m_floating_flag) SetWindowPos(m_htool_bar, NULL, 10,0, LOWORD(lp),HIWORD(lp), 0);
break;
case WM_LBUTTONDOWN: // マウス左ボタン押上(ドラッグ終了)
tool_on_lbuttondown(hwnd);
break;
case WM_LBUTTONUP: // マウス左ボタン押上(ドラッグ開始)
tool_on_lbuttonup();
break;
case WM_MOUSEMOVE: // マウス移動(ドラッグ中)
tool_on_mousemove();
break;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
// マウス移動
void DOCK_SYS::tool_on_mousemove(){
if (!m_dock_context.m_now_dragging) return;
m_dock_context.drag(); // ドラッグ中
}
// マウス左ボタン押上
void DOCK_SYS::tool_on_lbuttondown(HWND hwnd){
if (m_dock_context.m_now_dragging) return;
m_dock_context.start_drag(hwnd); // ドラッグ開始
}
// マウス左ボタン押上
void DOCK_SYS::tool_on_lbuttonup(){
RECT drag_rc, dock_rc;
if (!m_dock_context.m_now_dragging) return;
m_dock_context.end_drag(); // ドラッグ終了
// ドッキング・フローティング判定
GetWindowRect(m_hdock_bar, &dock_rc);
POINT po;
GetCursorPos((POINT*)&po);
drag_rc.left=po.x-m_dock_context.m_cursor_offset.x;
drag_rc.top =po.y-m_dock_context.m_cursor_offset.y;
drag_rc.right = drag_rc.left + m_dock_context.m_drag_size.cx;
drag_rc.bottom= drag_rc.top + m_dock_context.m_drag_size.cy;
// ドッキング判定
if (drag_rc.left<=dock_rc.right && drag_rc.right>=dock_rc.left
&& drag_rc.top<=dock_rc.bottom && drag_rc.bottom>=dock_rc.top){
do_dock();
}
// フローティング判定
else do_float(drag_rc.left, drag_rc.top);
}
// ドッキングシステム生成
DOCK_SYS::create(HWND main_hwnd, HWND child_view_hwnd){
m_now_nc_activing=0;
m_floating_flag=0;
m_main_frame=main_hwnd;
m_hview=child_view_hwnd;
regist_winc(TEXT("popup_frame"), (HBRUSH)(COLOR_BTNFACE+1), StaticPopupProc); // フローティング・フレーム
regist_winc(TEXT("tool_bar_frame"), (HBRUSH)(COLOR_BTNFACE+1), StaticToolBarFrameProc); // ツールバーの外枠
regist_winc(TEXT("dock_bar_frame"), (HBRUSH)(COLOR_BTNFACE+1), DefWindowProc); // ドックバー
HINSTANCE hInstance=GetModuleHandle(NULL);
m_popup_frame= CreateWindowEx(
WS_EX_TOOLWINDOW, TEXT("popup_frame"), NULL, WS_OVERLAPPEDWINDOW | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
300, 170, 200, 100, main_hwnd, NULL, hInstance, (LPVOID)this
);
m_htool_bar_frame= CreateWindow(
TEXT("tool_bar_frame"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, 200, 100, main_hwnd, NULL, hInstance, (LPVOID)this
);
m_hdock_bar = CreateWindow(
TEXT("dock_bar_frame"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, 200, 100, main_hwnd, NULL, hInstance, (LPVOID)this
);
do_dock();
}
// タイトルバーのアクティブ化・非アクティブ化
void DOCK_SYS::on_ncactivate(HWND hwnd, WPARAM wp){
if (m_now_nc_activing) return;
m_now_nc_activing=1;
SendMessage(m_main_frame, WM_NCACTIVATE, wp, 0);
SendMessage(m_popup_frame, WM_NCACTIVATE, wp, 0);
m_now_nc_activing=0;
}
// ドッキング
void DOCK_SYS::do_dock(){
SetWindowPos(m_htool_bar_frame, NULL, 0,0, 0,0, SWP_NOSIZE);
if (!m_floating_flag) return;
SetParent(m_htool_bar_frame, m_hdock_bar);
m_floating_flag = 0;
ShowWindow(m_popup_frame, SW_HIDE);
recalc_layout();
}
// フローティング
void DOCK_SYS::do_float(int x, int y){
SetWindowPos(m_popup_frame, NULL, x, y, 0,0, SWP_NOSIZE);
if (m_floating_flag) return;
SetParent(m_htool_bar_frame, m_popup_frame);
m_floating_flag = 1;
SetWindowPos(m_htool_bar_frame, NULL, 0,0, 0,0, SWP_NOSIZE);
ShowWindow(m_popup_frame, SW_SHOW);
recalc_layout();
}
// レイアウト再計算
void DOCK_SYS::recalc_layout(){
if (IsIconic(m_main_frame)) return;
RECT rc;
SIZE tool_size;
// 子ウィンドウ位置の再計算
SendMessage(m_htool_bar, TB_GETMAXSIZE, 0, (LPARAM)&tool_size); // ツールバー・サイズ取得
DWORD padding=SendMessage(m_htool_bar, TB_GETPADDING, 0, 0);
tool_size.cx+=LOWORD(padding);
tool_size.cy+=HIWORD(padding);
GetClientRect(m_main_frame, &rc);
if (!m_floating_flag) rc.top =tool_size.cy;
// ビューウィンドウ位置サイズ
if (IsWindow(m_hview)) SetWindowPos(m_hview, NULL, rc.left, rc.top, rc.right, rc.bottom-rc.top, 0);
// ドックバー位置サイズ
SetWindowPos(m_hdock_bar, NULL, 0, 0, rc.right, rc.top, 0);
// ポップアップ・ウィンドウ位置サイズ
if(m_floating_flag){
rc.left=rc.top=0;
rc.right=tool_size.cx;
rc.bottom=tool_size.cy;
AdjustWindowRectEx(&rc, GetWindowLong(m_popup_frame, GWL_STYLE), FALSE, GetWindowLong(m_popup_frame, GWL_EXSTYLE));
SetWindowPos(m_popup_frame, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, SWP_NOMOVE);
}
// ツールバー横サイズ補正
GetClientRect(GetParent(m_htool_bar_frame), &rc);
SetWindowPos(m_htool_bar_frame, NULL, 0, 0, rc.right, tool_size.cy, 0);
}
// ウィンドウクラス登録
DOCK_SYS::regist_winc(char *caption, HBRUSH hbr_bg, WNDPROC proc){
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = proc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = GetModuleHandle(NULL);
winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL, IDC_ARROW);
winc.hbrBackground = hbr_bg;
winc.lpszMenuName = NULL;
winc.lpszClassName = caption;
if (!RegisterClass(&winc)) return -1;
return 0;
}
//======================================================================================
//============ 以下 メインウィンドウ ・ ビューウィンドウ ==============================
//======================================================================================
// ビューウィンドウ・プロシージャ
LRESULT CALLBACK ChildViewProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
HDC hdc;
PAINTSTRUCT ps;
char str[]="ChildViewウィンドウ(座標0,0)";
switch (msg) {
case WM_LBUTTONDOWN:
SendMessage(GetParent(hwnd), WM_LBUTTONDOWN, wp, lp);
break;
case WM_PAINT:
hdc = BeginPaint(hwnd , &ps);
TextOut(hdc, 0, 0, str, lstrlen(str));
EndPaint(hwnd , &ps);
break;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
// メインウィンドウ・プロシージャ
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
static DOCK_SYS dock_sys; // ウィンドウ・ハンドルの一括化 構造体
static HWND hview;
switch (msg) {
case WM_CREATE:
hview= CreateWindowEx(
WS_EX_TOOLWINDOW, TEXT("child_view"), NULL, WS_CHILD | WS_VISIBLE,
0, 0, 200, 100, hwnd, NULL, ((LPCREATESTRUCT)(lp))->hInstance, NULL
);
dock_sys.create(hwnd, hview);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_NCACTIVATE: // タイトルバーのアクティブ化・非アクティブ化
dock_sys.on_ncactivate(hwnd, wp);
break;
case WM_SIZE:
dock_sys.recalc_layout();
break;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow ) {
MSG msg;
WNDCLASS winc;
HWND hwnd;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL, IDC_ARROW);
winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winc.lpszMenuName = NULL;
winc.lpszClassName = TEXT("main_frame");
if (!RegisterClass(&winc)) return -1; // メイン・ウィンドウ
winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winc.lpfnWndProc = ChildViewProc;
winc.lpszClassName = TEXT("child_view");
if (!RegisterClass(&winc)) return -1; // ビューウィンドウ
hwnd = CreateWindow(
TEXT("main_frame"), TEXT("ドッキング・ツールバーのテスト"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
100, 100, 240, 200, NULL, NULL, hInstance, NULL
);
if (hwnd == NULL) return -1;
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
|
上記のソースはツールバーもドックバーもごちゃまぜなので
もうちょっとクラス化して下記でTOOL_BARクラスとDOCK_BARクラスを作っています。
動作は全く同じです。
| docking_test3_2.cpp |
#define _WIN32_IE 0x0501
#include <windows.h>
#include <commctrl.h>
// ドック・コンテキスト・構造体
class DOCK_CONTEXT {
public:
HRGN m_apply_rgn, m_work_rgn, m_work_rgn2, m_last_rgn; // リージョン
HDC m_desk_hdc; // デスクトップDC
int m_now_dragging; // ドラッグ中なら==1 そうでないなら==0
SIZE m_drag_size; // ドラッグ中の矩形サイズ
POINT m_cursor_offset; // ドラッグ中の矩形位置のマウス位置との差分
HBRUSH m_desk_old_brush; // デスクトップDC・ブラシ
HBRUSH m_half_tone_brush; // ハーフトーン・ブラシ
DOCK_CONTEXT(); // コンストラクタ
~DOCK_CONTEXT(); // デストラクタ
void start_drag(HWND hwnd); // ドラッグ開始
void drag(); // ドラッグ中
void end_drag(); // ドラッグ終了
};
// クラスの仮宣言
class DOCK_SYS;
// ツールバークラス
class TOOL_BAR {
public:
HWND m_hwnd, m_control_tool_bar, m_popup_frame; // 各HWND
DOCK_SYS *m_p_dock_sys; // ドッキング・ツールバー統括クラス・ポインタ
int m_floating_flag; // フローティング・フラグ 浮いてれば==1 そうでないなら==0
create(DOCK_SYS *p_dock_sys, TBBUTTON *tb_buttons, int tb_button_len); // ツールバー生成
// ポップアップ・フレーム・プロシージャ
PopupProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
static LRESULT CALLBACK StaticPopupProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
// ツールバー・プロシージャ
ToolBarFrameProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
static LRESULT CALLBACK StaticToolBarFrameProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp);
};
// ドックバークラス
class DOCK_BAR {
public:
HWND m_hwnd;
};
// ドッキング・ツールバー統括クラス
class DOCK_SYS {
public:
HWND m_main_frame, m_hview; // 各HWND
int m_now_nc_activing; // WM_NCACTIVATEフラグ WM_NCACTIVATEの多重再送を防ぐ
DOCK_CONTEXT m_dock_context; // ドック・コンテキスト・構造体
DOCK_BAR m_dock_bar; // ドックバークラス
TOOL_BAR m_tool_bar; // ツールバークラス
regist_winc(char *caption, HBRUSH hbr_bg, WNDPROC proc); // ウィンドウクラス登録
create(HWND main_hwnd, HWND child_view_hwnd); // 生成
void on_ncactivate(HWND hwnd, WPARAM wp); // WM_NCACTIVATE 処理
void do_dock(); // ドッキング実行
void do_float(int x, int y); // フローティング実行
void recalc_layout(); // 子ウィンドウ位置再計算
void tool_on_lbuttondown(HWND hwnd); // ツールバー・マウス左ボタン押下
void tool_on_lbuttonup(); // ツールバー・マウス左ボタン押上
void tool_on_mousemove(); // ツールバー・マウス移動
} ;
// コンストラクタ
DOCK_CONTEXT::DOCK_CONTEXT(){
WORD gray_pattern[8];
HBITMAP gray_bitmap;
int i;
m_now_dragging=0;
// ハーフトーン・パレット生成
for (i=0;i<8;i++) gray_pattern[i] = (WORD)(0x5555 << (i & 1)); // 0x5555 は2bitで 01010101 01010101
gray_bitmap = CreateBitmap(8, 8, 1, 1, &gray_pattern);
if (gray_bitmap != NULL) {
m_half_tone_brush = ::CreatePatternBrush(gray_bitmap);
DeleteObject(gray_bitmap);
}
}
// デストラクタ
DOCK_CONTEXT::~DOCK_CONTEXT(){
DeleteObject(m_half_tone_brush); // ハーフトーン・パレット破棄
}
// ドラッグ開始
void DOCK_CONTEXT::start_drag(HWND hwnd){
HWND desk_hwnd;
RECT rc;
m_now_dragging=1;
SetCapture(hwnd);
// デスクトップDCを得る
desk_hwnd=GetDesktopWindow();
LockWindowUpdate(desk_hwnd);
m_desk_hdc= GetDCEx(desk_hwnd, NULL, DCX_WINDOW|DCX_CACHE|DCX_LOCKWINDOWUPDATE);
m_desk_old_brush=(HBRUSH)SelectObject(m_desk_hdc, m_half_tone_brush);
// ドラッグ・サイズとマウスとの座標差
GetWindowRect(hwnd, &rc);
m_drag_size.cx = rc.right-rc.left;
m_drag_size.cy = rc.bottom-rc.top;
GetCursorPos(&m_cursor_offset);
m_cursor_offset.x -= rc.left;
m_cursor_offset.y -= rc.top;
// リージョン生成
m_apply_rgn = CreateRectRgn(0, 0, 0, 0);
m_work_rgn = CreateRectRgn(0, 0, 0, 0);
m_work_rgn2 = CreateRectRgn(0, 0, 0, 0);
m_last_rgn = CreateRectRgn(0, 0, 0, 0);
}
// ドラッグ中
void DOCK_CONTEXT::drag(){
POINT po;
RECT rc;
GetCursorPos(&po);
po.x-=m_cursor_offset.x;
po.y-=m_cursor_offset.y;
SetRectRgn(m_work_rgn, po.x, po.y, po.x+m_drag_size.cx, po.y+m_drag_size.cy);
SetRectRgn(m_work_rgn2, po.x+4, po.y+4, po.x+m_drag_size.cx-4, po.y+m_drag_size.cy-4);
CombineRgn(m_apply_rgn, m_work_rgn, m_work_rgn2, RGN_XOR);
CombineRgn(m_work_rgn, m_apply_rgn, m_last_rgn, RGN_XOR);
// 反転による矩形描画
GetRgnBox(m_work_rgn, &rc);
SelectObject(m_desk_hdc, m_work_rgn);
PatBlt(m_desk_hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, PATINVERT);
// 最後に描画した部分保持(再反転して消去)
CombineRgn(m_last_rgn, m_apply_rgn, NULL, RGN_COPY);
}
// ドラッグ終了
void DOCK_CONTEXT::end_drag(){
RECT rc;
m_now_dragging=0;
ReleaseCapture();
// 最後に描画した部分を消去(再反転してるだけ)
GetRgnBox(m_apply_rgn, &rc);
SelectObject(m_desk_hdc, m_apply_rgn);
PatBlt(m_desk_hdc, rc.left, rc.top, rc.right-rc.left, rc.bottom-rc.top, PATINVERT);
// リージョン破棄
DeleteObject(m_apply_rgn);
DeleteObject(m_work_rgn);
DeleteObject(m_work_rgn2);
DeleteObject(m_last_rgn);
// デスクトップDCを解放
LockWindowUpdate(NULL);
if (m_desk_hdc) ReleaseDC(GetDesktopWindow(), m_desk_hdc);
SelectObject(m_desk_hdc, m_desk_old_brush);
}
// ツールバー生成
TOOL_BAR::create(DOCK_SYS *p_dock_sys, TBBUTTON *tb_buttons, int tb_button_len){
m_floating_flag=0;
m_p_dock_sys=p_dock_sys;
HINSTANCE hInstance=GetModuleHandle(NULL);
// ポップアップ・フレーム生成
m_popup_frame= CreateWindowEx(
WS_EX_TOOLWINDOW, TEXT("popup_frame"), NULL, WS_OVERLAPPEDWINDOW | WS_POPUP | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
300, 170, 200, 100, p_dock_sys->m_main_frame, NULL, hInstance, (LPVOID)this
);
InitCommonControls();
// コモンコントロールのツールバー生成
m_control_tool_bar = CreateToolbarEx(p_dock_sys->m_main_frame, WS_CHILD | TBSTYLE_AUTOSIZE, 0, 6,
(HINSTANCE)HINST_COMMCTRL, IDB_STD_SMALL_COLOR, tb_buttons, tb_button_len, 0, 0, 0, 0, sizeof (TBBUTTON)
);
// ツールバーのフレーム生成
m_hwnd= CreateWindow(
TEXT("tool_bar_frame"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, 200, 100, p_dock_sys->m_main_frame, NULL, hInstance, (LPVOID)this
);
SetParent(m_control_tool_bar, m_hwnd);
ShowWindow(m_control_tool_bar, SW_SHOWNA);
}
// ポップアップウィンドウ・プロシージャ(static版)
LRESULT CALLBACK TOOL_BAR::StaticPopupProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
TOOL_BAR *p_tool_bar =(TOOL_BAR*)GetWindowLong(hwnd, GWL_USERDATA);
if (!p_tool_bar && (msg==WM_NCCREATE || msg==WM_CREATE)){
p_tool_bar = (TOOL_BAR*)((LPCREATESTRUCT)lp)->lpCreateParams;
SetWindowLong(hwnd, GWL_USERDATA, (LONG)p_tool_bar);
}
if (p_tool_bar) return p_tool_bar->PopupProc(hwnd, msg, wp, lp);
return DefWindowProc(hwnd, msg, wp, lp);
}
// ポップアップウィンドウ・プロシージャ
TOOL_BAR::PopupProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
int res;
switch (msg) {
case WM_NCACTIVATE: // タイトルバーのアクティブ化・非アクティブ化
m_p_dock_sys->on_ncactivate(hwnd, wp);
break;
case WM_LBUTTONDOWN:m_p_dock_sys->tool_on_lbuttondown(hwnd); break; // ドラッグ開始
case WM_LBUTTONUP: m_p_dock_sys->tool_on_lbuttonup(); break; // ドラッグ終了
case WM_MOUSEMOVE: m_p_dock_sys->tool_on_mousemove(); break; // マウス移動(ドラッグ中)
case WM_NCHITTEST:
res=DefWindowProc(hwnd, msg, wp, lp);
if (res==HTCAPTION) return HTCLIENT;
return res;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
// ツールバーのフレームウィンドウ・プロシージャ(static版)
LRESULT CALLBACK TOOL_BAR::StaticToolBarFrameProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp){
TOOL_BAR *p_tool_bar =(TOOL_BAR*)GetWindowLong(hwnd, GWL_USERDATA);
if (!p_tool_bar && (msg==WM_NCCREATE || msg==WM_CREATE)){
p_tool_bar = (TOOL_BAR*)((LPCREATESTRUCT)lp)->lpCreateParams;
SetWindowLong(hwnd, GWL_USERDATA, (LONG)p_tool_bar);
}
if (p_tool_bar) return p_tool_bar->ToolBarFrameProc(hwnd, msg, wp, lp);
return DefWindowProc(hwnd, msg, wp, lp);
}
// ツールバーのフレームウィンドウ・プロシージャ
TOOL_BAR::ToolBarFrameProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
RECT rc, rc2;
HDC hdc;
PAINTSTRUCT ps;
switch (msg) {
case WM_PAINT:
hdc = BeginPaint(hwnd , &ps);
GetClientRect(hwnd, &rc);
rc.left=0; rc.top=0; rc.bottom=1; FillRect(hdc, &rc, GetSysColorBrush(COLOR_BTNSHADOW));
rc.top++; rc.bottom++; FillRect(hdc, &rc, GetSysColorBrush(COLOR_BTNHILIGHT));
if (!m_floating_flag){
// グリッパー描画
GetClientRect(hwnd, &rc);
rc.left+=2; rc.right=rc.left+3;
rc.top+=1; rc.bottom-=2;
rc2.left=rc.left; rc2.top=rc.top;
rc2.right=rc.right-1; rc2.bottom=rc.top+1; FillRect(hdc, &rc2, GetSysColorBrush(COLOR_BTNHILIGHT));
rc2.right=rc.left+1; rc2.bottom=rc.bottom-1; FillRect(hdc, &rc2, GetSysColorBrush(COLOR_BTNHILIGHT));
rc2.left=rc.right; rc2.top=rc.top;
rc2.right=rc.right-1; rc2.bottom=rc.bottom; FillRect(hdc, &rc2, GetSysColorBrush(COLOR_BTNSHADOW));
rc2.left=rc.left; rc2.top=rc.bottom;
rc2.right=rc.right; rc2.bottom=rc.bottom-1; FillRect(hdc, &rc2, GetSysColorBrush(COLOR_BTNSHADOW));
}
EndPaint(hwnd , &ps);
break;
case WM_SIZE:
SendMessage(m_control_tool_bar, WM_SIZE, wp, lp); // ツーバーのリサイズ
if (!m_floating_flag) SetWindowPos(m_control_tool_bar, NULL, 10,0, LOWORD(lp),HIWORD(lp), 0);
break;
case WM_LBUTTONDOWN:m_p_dock_sys->tool_on_lbuttondown(hwnd);break; // マウス左ボタン押下(ドラッグ終了)
case WM_LBUTTONUP: m_p_dock_sys->tool_on_lbuttonup(); break; // マウス左ボタン押上(ドラッグ開始)
case WM_MOUSEMOVE: m_p_dock_sys->tool_on_mousemove(); break; // マウス移動(ドラッグ中)
}
return DefWindowProc(hwnd, msg, wp, lp);
}
// マウス移動
void DOCK_SYS::tool_on_mousemove(){
if (!m_dock_context.m_now_dragging) return;
m_dock_context.drag(); // ドラッグ中
}
// マウス左ボタン押下
void DOCK_SYS::tool_on_lbuttondown(HWND hwnd){
if (m_dock_context.m_now_dragging) return;
m_dock_context.start_drag(hwnd); // ドラッグ開始
}
// マウス左ボタン押上
void DOCK_SYS::tool_on_lbuttonup(){
RECT drag_rc, dock_rc;
if (!m_dock_context.m_now_dragging) return;
m_dock_context.end_drag(); // ドラッグ終了
// ドッキング・フローティング判定
POINT po;
GetCursorPos(&po);
drag_rc.left=po.x-m_dock_context.m_cursor_offset.x;
drag_rc.top =po.y-m_dock_context.m_cursor_offset.y;
drag_rc.right = drag_rc.left + m_dock_context.m_drag_size.cx;
drag_rc.bottom= drag_rc.top + m_dock_context.m_drag_size.cy;
GetWindowRect(m_dock_bar.m_hwnd, &dock_rc);
// ドッキング判定
if (drag_rc.left<=dock_rc.right && drag_rc.right>=dock_rc.left
&& drag_rc.top<=dock_rc.bottom && drag_rc.bottom>=dock_rc.top){
do_dock();
}
// フローティング判定
else do_float(drag_rc.left, drag_rc.top);
}
// ドッキングシステム生成
DOCK_SYS::create(HWND main_hwnd, HWND child_view_hwnd){
m_now_nc_activing=0;
m_main_frame=main_hwnd;
m_hview=child_view_hwnd;
regist_winc(TEXT("popup_frame"), (HBRUSH)(COLOR_BTNFACE+1), TOOL_BAR::StaticPopupProc); // フローティング・フレーム
regist_winc(TEXT("tool_bar_frame"), (HBRUSH)(COLOR_BTNFACE+1), TOOL_BAR::StaticToolBarFrameProc); // ツールバーの外枠
regist_winc(TEXT("dock_bar_frame"), (HBRUSH)(COLOR_BTNFACE+1), DefWindowProc); // ドックバー
HINSTANCE hInstance=GetModuleHandle(NULL);
m_dock_bar.m_hwnd = CreateWindow(
TEXT("dock_bar_frame"), NULL, WS_CHILD | WS_VISIBLE | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
0, 0, 200, 100, main_hwnd, NULL, hInstance, (LPVOID)this
);
// ツールバーの生成
TBBUTTON tool_bar_buttons[] = {
{ STD_FILENEW, 1, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ STD_FILEOPEN, 2, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ STD_FILESAVE, 3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0 },
{ STD_COPY, 4, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ STD_CUT, 5, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ STD_DELETE, 6, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ 0, 0, TBSTATE_ENABLED, TBSTYLE_SEP, 0, 0, 0 },
{ VIEW_NEWFOLDER, 7, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
{ VIEW_PARENTFOLDER, 8, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0, 0 },
};
m_tool_bar.create(this, tool_bar_buttons, 7);
do_dock();
}
// タイトルバーのアクティブ化・非アクティブ化
void DOCK_SYS::on_ncactivate(HWND hwnd, WPARAM wp){
if (m_now_nc_activing) return;
m_now_nc_activing=1;
SendMessage(m_main_frame, WM_NCACTIVATE, wp, 0);
SendMessage(m_tool_bar.m_popup_frame, WM_NCACTIVATE, wp, 0);
m_now_nc_activing=0;
}
// ドッキング
void DOCK_SYS::do_dock(){
SetParent(m_tool_bar.m_hwnd, m_dock_bar.m_hwnd);
m_tool_bar.m_floating_flag = 0;
ShowWindow(m_tool_bar.m_popup_frame, SW_HIDE);
recalc_layout();
}
// フローティング
void DOCK_SYS::do_float(int x, int y){
SetWindowPos(m_tool_bar.m_popup_frame, NULL, x, y, 0,0, SWP_NOSIZE);
if (m_tool_bar.m_floating_flag) return;
SetParent(m_tool_bar.m_hwnd, m_tool_bar.m_popup_frame);
m_tool_bar.m_floating_flag = 1;
ShowWindow(m_tool_bar.m_popup_frame, SW_SHOW);
recalc_layout();
}
// レイアウト再計算
void DOCK_SYS::recalc_layout(){
if (IsIconic(m_main_frame)) return;
RECT rc;
SIZE tool_size;
// 子ウィンドウ位置の再計算
SendMessage(m_tool_bar.m_control_tool_bar, TB_GETMAXSIZE, 0, (LPARAM)&tool_size); // ツールバー・サイズ取得
DWORD padding=SendMessage(m_tool_bar.m_control_tool_bar, TB_GETPADDING, 0, 0);
tool_size.cx+=LOWORD(padding);
tool_size.cy+=HIWORD(padding);
GetClientRect(m_main_frame, &rc);
if (!m_tool_bar.m_floating_flag) rc.top =tool_size.cy;
// ビューウィンドウ位置サイズ
if (IsWindow(m_hview)) SetWindowPos(m_hview, NULL, rc.left, rc.top, rc.right, rc.bottom-rc.top, 0);
// ドックバー位置サイズ
SetWindowPos(m_dock_bar.m_hwnd, NULL, 0, 0, rc.right, rc.top, 0);
// ポップアップ・ウィンドウ位置サイズ
if(m_tool_bar.m_floating_flag){
rc.left=rc.top=0;
rc.right=tool_size.cx;
rc.bottom=tool_size.cy;
AdjustWindowRectEx(&rc, GetWindowLong(m_tool_bar.m_popup_frame, GWL_STYLE),
FALSE, GetWindowLong(m_tool_bar.m_popup_frame, GWL_EXSTYLE));
SetWindowPos(m_tool_bar.m_popup_frame, NULL, 0, 0, rc.right-rc.left, rc.bottom-rc.top, SWP_NOMOVE);
}
// ツールバー横サイズ補正
GetClientRect(GetParent(m_tool_bar.m_hwnd), &rc);
SetWindowPos(m_tool_bar.m_hwnd, NULL, 0, 0, rc.right, tool_size.cy, 0);
}
// ウィンドウクラス登録
DOCK_SYS::regist_winc(char *caption, HBRUSH hbr_bg, WNDPROC proc){
WNDCLASS winc;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = proc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = GetModuleHandle(NULL);
winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL, IDC_ARROW);
winc.hbrBackground = hbr_bg;
winc.lpszMenuName = NULL;
winc.lpszClassName = caption;
if (!RegisterClass(&winc)) return -1;
return 0;
}
//======================================================================================
//============ 以下 メインウィンドウ ・ ビューウィンドウ ==============================
//======================================================================================
// ビューウィンドウ・プロシージャ
LRESULT CALLBACK ChildViewProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
HDC hdc;
PAINTSTRUCT ps;
char str[]="ChildViewウィンドウ(座標0,0)";
switch (msg) {
case WM_LBUTTONDOWN:
SendMessage(GetParent(hwnd), WM_LBUTTONDOWN, wp, lp);
break;
case WM_PAINT:
hdc = BeginPaint(hwnd , &ps);
TextOut(hdc, 0, 0, str, lstrlen(str));
EndPaint(hwnd , &ps);
break;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
// メインウィンドウ・プロシージャ
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
static DOCK_SYS dock_sys; // ウィンドウ・ハンドルの一括化 構造体
static HWND hview;
switch (msg) {
case WM_CREATE:
hview= CreateWindowEx(
WS_EX_TOOLWINDOW, TEXT("child_view"), NULL, WS_CHILD | WS_VISIBLE,
0, 0, 200, 100, hwnd, NULL, ((LPCREATESTRUCT)(lp))->hInstance, NULL
);
dock_sys.create(hwnd, hview);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_NCACTIVATE: // タイトルバーのアクティブ化・非アクティブ化
dock_sys.on_ncactivate(hwnd, wp);
break;
case WM_SIZE:
dock_sys.recalc_layout();
break;
}
return DefWindowProc(hwnd, msg, wp, lp);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR lpCmdLine, int nCmdShow ) {
MSG msg;
WNDCLASS winc;
HWND hwnd;
winc.style = CS_HREDRAW | CS_VREDRAW;
winc.lpfnWndProc = WndProc;
winc.cbClsExtra = winc.cbWndExtra = 0;
winc.hInstance = hInstance;
winc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
winc.hCursor = LoadCursor(NULL, IDC_ARROW);
winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winc.lpszMenuName = NULL;
winc.lpszClassName = TEXT("main_frame");
if (!RegisterClass(&winc)) return -1; // メイン・ウィンドウ
winc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
winc.lpfnWndProc = ChildViewProc;
winc.lpszClassName = TEXT("child_view");
if (!RegisterClass(&winc)) return -1; // ビューウィンドウ
hwnd = CreateWindow(
TEXT("main_frame"), TEXT("ドッキング・ツールバーのテスト"),
WS_OVERLAPPEDWINDOW | WS_VISIBLE | WS_CLIPCHILDREN,
100, 100, 240, 200, NULL, NULL, hInstance, NULL
);
if (hwnd == NULL) return -1;
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
|