第206章 タブコントロールの新しいスタイル


タブコントロールについてはすでに 第69章で出てきました。 今回は、このコントロールの新しいスタイルについてやります。



左の図はタブコントロールのスタイルを TCS_BUTTONS | TCS_FLATBUTTONS | TCS_HOTTRACK に設定したものです。「粂井」ボタンが押されていて 「鈴木」ボタンにマウスをポイントしています。 TCS_HOTTRACKがないとマウスをポイントしても浮き上がりません。 さらにこのプログラムではタブコントロールから TCS_EX_FLATSEPARATORSスタイルを取り除いてタブとタブの 境界線を描画しないようにしています。



さて、以上の設定だけですと別に問題は起こりません。 しかし、タブ位置を左右に変えたり、タブが2列以上にわたって表示 (TCS_MULTILINE)されるととたんにおかしなことが起こります。 今回は、問題の起こらないスタイルのみについて解説します。

// tab01.cpp #ifndef STRICT #define STRICT #endif #include <windows.h> #include <commctrl.h> #define ID_TAB 100 #define ID_STATIC 101 LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); LRESULT CALLBACK MyStaticProc(HWND, UINT, WPARAM, LPARAM); ATOM InitApp(HINSTANCE); BOOL InitInstance(HINSTANCE, int); char szClassName[] = "tab01"; //ウィンドウクラス HINSTANCE hInst; HWND hTab; WNDPROC OrgStaticProc; //元もとのスタティックコントロールのプロシージャ

この部分はあまり説明はいりませんね。 ビルドする前にコモンコントロールの準備を忘れないでください。

int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) { MSG msg; hInst = hCurInst; if (!InitApp(hCurInst)) return FALSE; if (!InitInstance(hCurInst, nCmdShow)) return FALSE; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return msg.wParam; } //ウィンドウ・クラスの登録 ATOM InitApp(HINSTANCE hInst) { WNDCLASSEX wc; wc.cbSize = sizeof(WNDCLASSEX); wc.style = CS_HREDRAW | CS_VREDRAW; wc.lpfnWndProc = WndProc; //プロシージャ名 wc.cbClsExtra = 0; wc.cbWndExtra = 0; wc.hInstance = hInst;//インスタンス wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); wc.hCursor = LoadCursor(NULL, IDC_ARROW); wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); wc.lpszMenuName = "MYMENU"; //メニュー名 wc.lpszClassName = (LPCSTR)szClassName; wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); return (RegisterClassEx(&wc)); } //ウィンドウの生成 BOOL InitInstance(HINSTANCE hInst, int nCmdShow) { HWND hWnd; hWnd = CreateWindow(szClassName, "猫でもわかるタブコントロール", //タイトルバーにこの名前が表示されます WS_OVERLAPPEDWINDOW, //ウィンドウの種類 CW_USEDEFAULT, //X座標 CW_USEDEFAULT, //Y座標 190, //幅 130, //高さ NULL, //親ウィンドウのハンドル、親を作るときはNULL NULL, //メニューハンドル、クラスメニューを使うときはNULL hInst, //インスタンスハンドル NULL); if (!hWnd) return FALSE; ShowWindow(hWnd, nCmdShow); UpdateWindow(hWnd); return TRUE; }

これは、いつもと同じです。

//ウィンドウプロシージャ LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) { int id; static HWND hStatic; INITCOMMONCONTROLSEX ic; TCITEM ti; RECT rc; DWORD dwStyle; switch (msg) { case WM_CREATE: ic.dwSize = sizeof(INITCOMMONCONTROLSEX); ic.dwICC = ICC_TAB_CLASSES; InitCommonControlsEx(&ic); hTab = CreateWindowEx(0, WC_TABCONTROL, "", WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS |TCS_BUTTONS | TCS_FLATBUTTONS | TCS_HOTTRACK, 0, 0, 0, 0, hWnd, (HMENU)ID_TAB, hInst, NULL); hStatic = CreateWindowEx(0, "STATIC", "", WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hWnd, (HMENU)ID_STATIC, hInst, NULL); dwStyle = TabCtrl_GetExtendedStyle(hTab); dwStyle &= ~TCS_EX_FLATSEPARATORS; TabCtrl_SetExtendedStyle(hTab, dwStyle); SendMessage(hTab, WM_SETFONT, (WPARAM)GetStockObject(DEFAULT_GUI_FONT), 0); memset(&ti, 0, sizeof(TCITEM)); ti.mask = TCIF_TEXT; ti.pszText = "粂井"; TabCtrl_InsertItem(hTab, 0, &ti); ti.pszText = "田中"; TabCtrl_InsertItem(hTab, 1, &ti); ti.pszText = "鈴木"; TabCtrl_InsertItem(hTab, 2, &ti); OrgStaticProc = (WNDPROC)GetWindowLong(hStatic, GWL_WNDPROC); if (SetWindowLong(hStatic, GWL_WNDPROC, (LONG)MyStaticProc) == 0) MessageBox(hWnd, "Error", "Error", MB_OK); break; case WM_SIZE: GetClientRect(hWnd, &rc); TabCtrl_AdjustRect(hTab, FALSE, &rc); MoveWindow(hTab, 0, 0, LOWORD(lp), HIWORD(lp), TRUE); MoveWindow(hStatic, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE); break; case WM_NOTIFY: switch (((NMHDR *)lp)->code) { case TCN_SELCHANGE: InvalidateRect(hTab, NULL, TRUE); InvalidateRect(hStatic, NULL, TRUE); break; } break; case WM_CLOSE: id = MessageBox(hWnd, "終了してもよいですか", "終了確認", MB_YESNO | MB_ICONQUESTION); if (id == IDYES) { if (SetWindowLong(hStatic, GWL_WNDPROC, (LONG)OrgStaticProc) == 0) MessageBox(hWnd, "サブクラス化解除失敗", "Error", MB_OK); DestroyWindow(hWnd); } break; case WM_DESTROY: PostQuitMessage(0); break; default: return (DefWindowProc(hWnd, msg, wp, lp)); } return 0; }

WM_CREATEメッセージが来たら、InitCommonControlsEx関数でコモンコントロールを 初期化します。INITCOMMONCONTROLSEX構造体のdwICCメンバは ICC_TAB_CLASSESに設定します。

CreateWindowEx関数でタブコントロールとスタティックコントロールを作成します。 タブコントロールにTCS_BUTTONのスタイルを設定するとタブの部分が ボタンになります。さらにTBS_FLATBUTTONS(Comctl32.dll Ver4.71以降) を加えるとフラットボタンになります。

TCS_HOTTRACK(Ver4.70以降)を加えるとポイントされているアイテムが 強調されます。フラットボタンであれば浮き上がります。タブであれば 色が変わります。

また、拡張スタイルとしてTCS_EX_FLATSEPARATORSがあります。 これは、タブとタブの間に区切りを入れます。 TCS_BUTTONS | TCS_FLATBUTTONSが設定されている時のみ影響します。 TCS_FLATBUTTONSにはデフォルトで設定されています。

さて、拡張スタイルを取得するにはTabCtrl_GetExtendedStyleマクロ (Ver4.71以降)を使います。

DWORD TabCtrl_GetExtendedStyle( HWND hwndTab );

hwndTabにはタブコントロールのハンドルを指定します。 拡張スタイルを設定するにはTabCtrl_SetExtendedStyleマクロ (Ver4.71以降)を使います。

DWORD TabCtrl_SetExtendedStyle( HWND hwndTab, DWORD dwExStyle );

hwndTabにはタブコントロールのハンドル、 dwExStyleには拡張スタイルを指定します。

さて、タブコントロールのフォントを設定するには タブコントロールにWM_SETFONTメッセージを送ります。 (第194章参照)

従来のTC_ITEM構造体(第69章参照)は TCITEM構造体に名前が変更になりました。 これは、次のように定義されています。

typedef struct tagTCITEM { UINT mask; #if (_WIN32_IE >= 0x0300) DWORD dwState; DWORD dwStateMask; #else UINT lpReserved1; UINT lpReserved2; #endif LPTSTR pszText; int cchTextMax; int iImage; LPARAM lParam; } TCITEM, FAR *LPTCITEM;

使い方はTC_ITEM構造体と全く同じです。

TabCtrl_InsertItemマクロでアイテムをを挿入したら、 スタティックコントロールをサブクラス化します。

WM_SIZEメッセージ、TCN_SELCHANGE通知メッセージの処理は 従来と同じです。(第69章参照)

//サブクラス化されたスタティックコントロールのプロシージャ LRESULT CALLBACK MyStaticProc(HWND hStatic, UINT msg, WPARAM wp, LPARAM lp) { HDC hdc; PAINTSTRUCT ps; int nNo; static char szStr[3][64] = {"粂井のページです。", "田中のページです。", "鈴木のページです。"}; switch (msg) { case WM_PAINT: hdc = BeginPaint(hStatic, &ps); nNo = TabCtrl_GetCurSel(hTab); SetBkMode(hdc, TRANSPARENT); TextOut(hdc, 10, 10, szStr[nNo], lstrlen(szStr[nNo])); EndPaint(hStatic, &ps); break; default: return CallWindowProc(OrgStaticProc, hStatic, msg, wp, lp); } return 0; }

サブクラス化されたスタティックコントロールのプロシージャです。 TabCtrl_GetCurselマクロで得たインデックスで表示する内容を変えています。

さて、今回のプログラムをもとにタブコントロールのスタイルをいろいろ変化させて 実験してみて下さい。特に縦表示(TCS_VERTICA)の時どのようなことが起こるか 実験してみて下さい。


[SDK第3部 Index] [総合Index] [Previous Chapter] [Next Chapter]

Update 04/Jun/1999 By Y.Kumei
当ホーム・ページの一部または全部を無断で複写、複製、 転載あるいはコンピュータ等のファイルに保存することを禁じます。