/***********************************
オーナードローサンプル
2002.Jun.25
K_Yaguchi
************************************/
#include <windows.h>
#define ClassName "OwnerDrawSample"
#define ICONW 16
#define ICONH 16
#define ICONCOUNT 5
#define IDM_MENU 102
LPCTSTR str[] = {
"マイコンピュータ",
"ドライブ",
"Internet Explorer",
"フォルダ",
"エクスプローラ"
};
HINSTANCE hInst;
/***********************
選択アイコン描画
************************/
BOOL Draw3DIcon(HDC hdc, RECT rc) {
HBRUSH hBrush;
// 左辺と上辺
rc.right = ICONW + 4;
hBrush = CreateSolidBrush(0xFFFFFF);
FillRect(hdc, &rc, hBrush);
DeleteObject(hBrush);
// 右辺と下辺
rc.left += 1;
rc.top += 1;
hBrush = CreateSolidBrush(0x424142);
FillRect(hdc, &rc, hBrush);
DeleteObject(hBrush);
// 真ん中は塗りつぶし
rc.right -= 1;
rc.bottom -= 1;
hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
FillRect(hdc, &rc, hBrush);
DeleteObject(hBrush);
return TRUE;
}
/*****************************
メニューアイコン描画
*****************************/
BOOL DrawMenuIcon(LPDRAWITEMSTRUCT dis) {
HDC hdc;
HBITMAP hOldBmp;
BOOL ret;
hdc = CreateCompatibleDC(0);
hOldBmp = (HBITMAP)SelectObject(hdc, LoadBitmap(hInst, "IDB_BITMAP"));
// 切り抜き
ret = BitBlt(
dis->hDC,
dis->rcItem.left + 2, dis->rcItem.top + 2,
ICONW, ICONH,
hdc,
ICONW * dis->itemData, 0,
SRCCOPY
);
DeleteObject(SelectObject(hdc, hOldBmp));
DeleteDC(hdc);
return ret;
}
/**************************************
オーナードロー用メニュー作成
**************************************/
HMENU CreateOwnerDrawMenu(void) {
HMENU hMenu;
int i;
hMenu = CreatePopupMenu();
for(i = 0; i < ICONCOUNT; i++)
AppendMenu(hMenu, MF_OWNERDRAW, IDM_MENU + i, (LPCTSTR)i);
return hMenu;
}
/*********************************
メニューアイテム初期処理
**********************************/
BOOL MeasureItem(LPMEASUREITEMSTRUCT mis) {
HDC hdc;
SIZE sz;
HFONT hFont, hOldFont;
hdc = GetDC(0);
// メニューのフォント
hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
// メニューの大きさを計算
hOldFont = (HFONT)SelectObject(hdc, hFont);
GetTextExtentPoint32(hdc, str[mis->itemData], lstrlen(str[mis->itemData]), &sz);
mis->itemHeight = sz.cy + 8;
mis->itemWidth = sz.cx + ICONW + 10;
SelectObject(hdc, hOldFont);
ReleaseDC(0, hdc);
return TRUE;
}
/********************************
メニューアイテムの描画
*********************************/
BOOL DrawItem(LPDRAWITEMSTRUCT dis) {
HFONT hFont, hOldFont;
HBRUSH hBrush;
RECT rc;
// メニューのフォント
hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
hOldFont = (HFONT)SelectObject(dis->hDC, hFont);
rc = dis->rcItem;
if(dis->itemState & ODS_SELECTED) {
// 選択状態
hBrush = CreateSolidBrush(GetSysColor(COLOR_HIGHLIGHT));
SetTextColor(dis->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
Draw3DIcon(dis->hDC, dis->rcItem);
rc.left = ICONW + 6;
FillRect(dis->hDC, &rc, hBrush); // アイコンを除いた領域を塗りつぶす
}
else {
// 非選択状態
hBrush = CreateSolidBrush(GetSysColor(COLOR_MENU));
SetTextColor(dis->hDC, GetSysColor(COLOR_MENUTEXT));
FillRect(dis->hDC, &rc, hBrush);
}
DrawMenuIcon(dis); // アイコン描画
SetBkMode(dis->hDC, TRANSPARENT); // SetBkColorでもいいけどね
TextOut(
dis->hDC,
dis->rcItem.left + ICONW + 10,
dis->rcItem.top + 4,
str[dis->itemData], lstrlen(str[dis->itemData])
);
DeleteObject(hBrush);
SelectObject(dis->hDC, hOldFont);
return TRUE;
}
/******************************
ウィンドウプロージャ
*******************************/
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
HDC hdc;
PAINTSTRUCT ps;
POINT po;
static HMENU hMenu1;
static HMENU hMenu2;
const char txt[] = "右クリックでメニューが出ます";
switch (msg) {
case WM_DESTROY:
DestroyMenu(hMenu1);
DestroyMenu(hMenu2);
PostQuitMessage(0);
break;
case WM_CREATE:
hMenu1 = CreateMenu(); // メニュー作成
hMenu2 = CreateOwnerDrawMenu(); // ポップアップメニュー作成
AppendMenu(hMenu1, MF_ENABLED | MF_POPUP | MF_STRING, (UINT)hMenu2, "メニュー"); // メニューバーの項目
SetMenu(hWnd, hMenu1);
DrawMenuBar(hWnd);
break;
case WM_RBUTTONUP:
po.x = LOWORD(lp);
po.y = HIWORD(lp);
ClientToScreen(hWnd, &po);
TrackPopupMenu(
hMenu2, TPM_LEFTALIGN | TPM_TOPALIGN,
po.x, po.y, 0, hWnd, NULL
);
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc, 50, 90, txt, lstrlen(txt));
EndPaint(hWnd, &ps);
break;
case WM_MEASUREITEM:
MeasureItem((LPMEASUREITEMSTRUCT)lp); // 初期処理
return TRUE;
case WM_DRAWITEM:
DrawItem((LPDRAWITEMSTRUCT)lp); // 描画
return TRUE;
default:
return DefWindowProc(hWnd, msg, wp, lp);
}
return 0;
}
/***************
メイン
****************/
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst, PSTR lpCmdLine, int nCmdShow) {
HWND hWnd;
MSG msg;
WNDCLASS wc;
hInst = hInstance;
// ウィンドウクラス登録
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszMenuName = NULL;
wc.lpszClassName = ClassName;
if (!RegisterClass(&wc)) return 0;
// オーナーウィンドウ
hWnd = CreateWindowEx(
WS_EX_CONTROLPARENT,
ClassName, "オーナードロー",
WS_OVERLAPPEDWINDOW | WS_VISIBLE,
CW_USEDEFAULT, CW_USEDEFAULT ,
320, 260,
NULL, NULL ,
hInstance, NULL
);
if (hWnd == NULL) return NULL;
// メッセージループ
while(GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// ウィンドウクラス解除
UnregisterClass(ClassName, hInstance);
return msg.wParam;
}
|