
//ウインドウプロシージャ
int CALLBACK WndProc(HWND hWnd, unsigned wMessage,
WPARAM wParam, LPARAM lParam)
{
HDC hdc;
PAINTSTRUCT ps;
switch (wMessage)
{
case WM_CREATE:
CenterWindow(hWnd);
CreateRebar(hWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_SIZE:
MoveRebar(hWnd);
break;
case WM_PAINT:
hdc = BeginPaint (hWnd, &ps);
EndPaint (hWnd, &ps);
return 0;
case WM_NOTIFY:
return DoNotify(hWnd, wParam, lParam);
}
return (DefWindowProc(hWnd, wMessage, wParam, lParam));
}
ここで、重要なのはWM_CREATE,WM_SIZE,WM_NOTIFYの3つの部分です。
HWND WINAPI CreateRebar(HWND hWndOwner)
{
REBARINFO rbi;
REBARBANDINFO rbBand;
RECT rc;
HWND hWndCB, hWndTB, hWndRB;
DWORD dwBtnSize;
INITCOMMONCONTROLSEX icex;
//Coolbarを作る
icex.dwSize = sizeof(INITCOMMONCONTROLSEX);
icex.dwICC = ICC_COOL_CLASSES|ICC_BAR_CLASSES;
InitCommonControlsEx(&icex);
hWndRB = CreateWindowEx(WS_EX_TOOLWINDOW,
REBARCLASSNAME,
NULL,
WS_BORDER |
WS_CHILD |
WS_VISIBLE |
WS_CLIPCHILDREN |
WS_CLIPSIBLINGS |
RBS_VARHEIGHT |
RBS_BANDBORDERS |
CCS_NODIVIDER |
CCS_NOPARENTALIGN |
// CCS_VERT | //垂直バー
0,
0,0,200,100,
hWndOwner,
(HMENU)ID_REBAR,
Instance,
NULL);
if(!hWndRB) return NULL;
rbi.cbSize = sizeof(REBARINFO);
rbi.fMask = 0;
rbi.himl = (HIMAGELIST)NULL;
if(!SendMessage(hWndRB, RB_SETBARINFO, 0, (LPARAM)&rbi)) return NULL;
//コンボボックスを作ってCoolbarに入れる
hWndCB=CreateComboBox(hWndRB);
GetWindowRect(hWndCB, &rc);
rbBand.cbSize = sizeof(REBARBANDINFO);
rbBand.fMask = RBBIM_TEXT |
RBBIM_BACKGROUND |
RBBIM_STYLE |
RBBIM_CHILDSIZE |
RBBIM_SIZE |
RBBIM_CHILD |
RBBIM_ID;
rbBand.fStyle = RBBS_CHILDEDGE |
RBBS_FIXEDBMP |
RBBS_GRIPPERALWAYS;
rbBand.hbmBack= LoadBitmap(Instance, MAKEINTRESOURCE(IDB_BACKGRND));
rbBand.wID = ID_COMBOBOX;
rbBand.lpText = TEXT("ComboBox");
rbBand.cch = 2;
rbBand.hwndChild = hWndCB;
rbBand.cxMinChild = rc.right - rc.left;
rbBand.cyMinChild = rc.bottom - rc.top;
rbBand.cx = 200;
SendMessage(hWndRB, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
//ツールバーを作ってCoolbarに入れる
hWndTB = CreateToolbar(hWndOwner);
GetWindowRect(hWndTB, &rc);
dwBtnSize = SendMessage(hWndTB, TB_GETBUTTONSIZE, 0,0);
rbBand.fMask = RBBIM_BACKGROUND |
RBBIM_STYLE |
RBBIM_CHILDSIZE |
RBBIM_SIZE |
RBBIM_CHILD |
RBBIM_ID |
0;
rbBand.wID = ID_TOOLBAR;
rbBand.hwndChild = hWndTB;
rbBand.cxMinChild = rc.right - rc.left;
rbBand.cyMinChild = HIWORD(dwBtnSize);
rbBand.cx = 150;
SendMessage(hWndRB, RB_INSERTBAND, (WPARAM)-1, (LPARAM)&rbBand);
return (hWndRB);
}
rbBand.cbSize
構造体の大きさを入れます。sizeofを使うだけ。
rbBand.fMask
この構造体のどのメンバを使用するかを指定します。
RBBIM_TEXT lpTextメンバを使用する RBBIM_BACKGROUND hbmBackメンバを使用する RBBIM_STYLE fStyleメンバを使用する RBBIM_CHILDSIZE cxMinChild, cyMinChild, cyChild, cyMaxChild,cyIntegral メンバを使用する RBBIM_SIZE cxメンバを使用する RBBIM_CHILD hwndChildメンバを使用する RBBIM_ID wIDメンバを有効にするrbBand.fStyle
RBBS_CHILDEDGE バーの上下に境界線をつける RBBS_FIXEDBMP 背景のビットマップを固定する RBBS_GRIPPERALWAYS サイズ変更用のグリップをつけるrbBand.hbmBack
rbBand.wID
コントロールのIDを設定する。
rbBand.lpText
これを使うと、コントロールの左にこの文字列が表示される。
rbBand.cch
lpTextのサイズらしいのだが、サンプルには2になっていた。よくわからん。
rbBand.hwndChild
Coolbarに入れるコントロール(子ウインドウ)のハンドル
rbBand.cxMinChild
横幅の最小値
rbBand.cyMinChild
高さの最小値
rbBand.cx
横幅の初期値
構造体の設定が終わったらSendMessageを使ってRB_INSERTBANDを送ります。この時、wParamにはコントロールを入れる場所(0を指定すると先頭に、−1を指定すると最後に追加される)、lParamにはさっきの構造体のアドレスを渡します。
//コンボボックスの作成
HWND CreateComboBox(HWND hWnd)
{
HWND hWndCB;
char szString[64];
int i;
hWndCB = CreateWindowEx( 0,
TEXT("combobox"),
NULL,
WS_VISIBLE |
WS_CHILD |
WS_TABSTOP |
WS_VSCROLL |
WS_CLIPCHILDREN |
WS_CLIPSIBLINGS |
CBS_AUTOHSCROLL |
CBS_DROPDOWN |
0,
0,
0,
100,
200,
hWnd,
(HMENU)ID_COMBOBOX,
Instance,
NULL);
SendMessage(hWndCB, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), MAKELPARAM(TRUE, 0));
//コンボボックスにアイテムを入れる
for(i = 0; i < 25; i++){
wsprintf(szString, TEXT("Item %d"), i + 1);
SendMessage(hWndCB, CB_ADDSTRING, 0, (LPARAM)szString);
}
return hWndCB;
}
//ツールバーの作成
TBBUTTON tbb[] = {
{0, 0, TBSTATE_ENABLED, TBSTYLE_BUTTON , 0, 0},
{1, 1, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0},
{2, 2, TBSTATE_ENABLED, TBSTYLE_DROPDOWN, 0, 0},
{3, 3, TBSTATE_ENABLED, TBSTYLE_BUTTON, 0, 0}
};
HWND CreateToolbar(HWND hWnd)
{
HWND hTool;
hTool = CreateToolbarEx(hWnd,
WS_CHILD |
CCS_NOPARENTALIGN |
CCS_NORESIZE |
CCS_NODIVIDER |
TBSTYLE_FLAT |
TBSTYLE_WRAPABLE,
ID_TOOLBAR,
4,
Instance,
IDB_TOOLBAR,
tbb,
4,
0, 0, 16, 15,
sizeof(TBBUTTON));
SendMessage(hTool,TB_SETEXTENDEDSTYLE,0,TBSTYLE_EX_DRAWDDARROWS);
return hTool;
}
3カ所ほどあります。まずは真ん中のツールバースタイルの所です。ここはほとんど強調表示になっています。それぞれの意味は、
CCS_NORESIZE
ツールバーの大きさを自由に変更できるようにします。これをつけないと、うまく大きさを変えれません。
CCS_NODIVIDER
ツールバーの上につく境界線を無くします。
TBSTYLE_FLAT
フラットなツールバーにします。これをつけると自動的に、透明なツールバーになります。
TBSTYLE_WRAPABLE
横幅が小さくなりすぎたときに自動的に折り返すようにします。Coolbarでは基本的に折り返しはないので、このフラグは必要ありませんがCoolbarを縦型にするときには必要です。
次は、残りの2カ所です。この二つはどちらもドロップダウンボタン付きのボタンを作るためのものです。サンプルの”C”のボタンをみてください。ボタンの右側に小さな三角がありますね、これがドロップダウンボタンです。ドロップダウンボタンを作るには、TBBUTTON構造体のボタンのスタイルをTBSTYLE_DROPDOWNにして、ツールバーの拡張スタイルとしてTBSTYLE_EX_DRAWDDARROWSをつけます。拡張スタイルの設定にはTB_SETEXTENDEDSTYLEメッセージを使います。
ドロップダウンボタンが押されると親ウインドウにWM_NOTIFYメッセージが送られてきます。その時のNOTIFYコードはTBN_DROPDOWNです。普通は、その時にメニューを表示します。
//WM_NOTIFYメッセージの処理
BOOL DoNotify(HWND hWnd, WPARAM wParam, LPARAM lParam)
{
#define lpNM ((LPNMHDR)lParam)
#define lpnmTB ((LPNMTOOLBAR)lParam)
RECT rc;
TPMPARAMS tpm;
HMENU hMenu,hPopupMenu = NULL; 99/01/18訂正
BOOL bRet = FALSE;
switch(lpNM->code){
case TBN_DROPDOWN:
SendMessage(lpnmTB->hdr.hwndFrom, TB_GETRECT,
(WPARAM)lpnmTB->iItem, (LPARAM)&rc);
MapWindowPoints(lpnmTB->hdr.hwndFrom,
HWND_DESKTOP, (LPPOINT)&rc, 2);
tpm.cbSize = sizeof(TPMPARAMS);
tpm.rcExclude.top = rc.top;
tpm.rcExclude.left = rc.left;
tpm.rcExclude.bottom = rc.bottom;
tpm.rcExclude.right = rc.right;
hMenu=LoadMenu(Instance,MAKEINTRESOURCE(IDR_POPUP)); 99/01/18訂正
hPopupMenu = GetSubMenu(hMenu,0);
TrackPopupMenuEx(hPopupMenu,
TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_VERTICAL,
rc.left, rc.bottom, hWnd, &tpm);
DestroyMenu(hMenu); 99/01/18追加
return (FALSE);
}
return FALSE;
}
特に大したことはしていないです。コードがTBN_DROPDOWNだったら、座標を調べてデスクトップの座標に変換して、TrackPopuMenuExでポップアップメニューを表示しているだけです。メニューはリソースエディタで作っておいてください。
//Coolバーをウインドウのサイズに合わせる
void MoveRebar(HWND hWnd)
{
RECT rc;
int x,y,cx,cy;
GetClientRect(hWnd, &rc);
x = 0;
y = 0;
cx = rc.right - rc.left;
cy = rc.bottom - rc.top;
MoveWindow( GetDlgItem(hWnd, ID_REBAR),x, y, cx, cy, TRUE);
}