source: dev/ProjectEditor/menu.cpp@ 84

Last change on this file since 84 was 84, checked in by dai_9181, 17 years ago
File size: 13.5 KB
Line 
1#include "common.h"
2
3HFONT hMenuFont;
4
5
6
7CMenuItemData::CMenuItemData(int item_index,int itemID,char *str,CMenuEx *pobj_ThisMenu,CSubMenuEx *pobj_SubMenu){
8 this->item_index=item_index;
9 this->itemID=itemID;
10 if(str){
11 this->str=(char *)HeapAlloc(hHeap,0,lstrlen(str)+1);
12 lstrcpy(this->str,str);
13 }
14 else this->str=0;
15 this->pobj_ThisMenu=pobj_ThisMenu;
16 this->pobj_SubMenu=pobj_SubMenu;
17
18
19 hIcon=0;
20 hGrayIcon=0;
21}
22CMenuItemData::~CMenuItemData(){
23 //メニュー文字列
24 if(str)
25 HeapDefaultFree(str);
26
27 //サブメニュー オブジェクトを破棄
28 if(pobj_SubMenu)
29 delete pobj_SubMenu;
30
31 //アイコン
32 if(hIcon) DestroyIcon(hIcon);
33
34 //淡色アイコン
35 if(hGrayIcon) DestroyIcon(hGrayIcon);
36}
37
38
39
40CMenuEx *pobj_MainMenu;
41
42CMenuEx::CMenuEx(HMENU hmenu){
43 hMenu=hmenu;
44
45 ppobj_MenuItemData=(CMenuItemData **)HeapAlloc(hHeap,0,1);
46 iMenuItemNum=0;
47}
48CMenuEx::~CMenuEx(){
49 int i;
50
51 //itemDataを解放
52 for(i=0;i<iMenuItemNum;i++){
53 delete ppobj_MenuItemData[i];
54 }
55 HeapDefaultFree(ppobj_MenuItemData);
56
57 DestroyMenu(hMenu);
58}
59
60void CMenuEx::EnableItem(UINT uIDEnableItem,UINT uEnable){
61 //メニューアイテムの有効化/無効化
62 EnableMenuItem(hMenu,uIDEnableItem,uEnable);
63}
64void CMenuEx::CheckMenu(UINT idItem,BOOL bChecked){
65 //メニューアイテムのチェックマークON/OFF
66 MENUITEMINFO MenuItemInfo;
67 MenuItemInfo.cbSize=sizeof(MENUITEMINFO);
68 MenuItemInfo.fMask=MIIM_STATE;
69 if(bChecked) MenuItemInfo.fState=MFS_CHECKED;
70 else MenuItemInfo.fState=MFS_UNCHECKED;
71
72 SetMenuItemInfo(hMenu,idItem,0,&MenuItemInfo);
73}
74BOOL CMenuEx::IsCheck(UINT idItem){
75 MENUITEMINFO MenuItemInfo;
76 MenuItemInfo.cbSize=sizeof(MENUITEMINFO);
77 MenuItemInfo.fMask=MIIM_STATE;
78 GetMenuItemInfo(hMenu,idItem,0,&MenuItemInfo);
79 if(MenuItemInfo.fState&MFS_CHECKED) return 1;
80 return 0;
81}
82void CMenuEx::RenameMenuItem(int item_index,char *str){
83 ppobj_MenuItemData[item_index]->str=(char *)HeapReAlloc(hHeap,0,ppobj_MenuItemData[item_index]->str,lstrlen(str)+1);
84 lstrcpy(ppobj_MenuItemData[item_index]->str,str);
85}
86void CMenuEx::RenameMenuItemByID(int itemID,char *str){
87 int i;
88 for(i=0;i<iMenuItemNum;i++){
89 if(ppobj_MenuItemData[i]->itemID==itemID){
90 RenameMenuItem(i,str);
91 return;
92 }
93 }
94}
95void CMenuEx::RemoveItem(int item_index){
96 //メニューアイテムの消去
97 //※ポップアップメニューの消去には対応していない
98
99 ::RemoveMenu(hMenu,item_index,MF_BYPOSITION);
100
101 //メニューアイテム拡張データオブジェクトを破棄
102 delete ppobj_MenuItemData[item_index];
103
104
105 iMenuItemNum--;
106
107 int i;
108 for(i=item_index;i<iMenuItemNum;i++){
109 ppobj_MenuItemData[i]=ppobj_MenuItemData[i+1];
110 }
111}
112void CMenuEx::InsertItem(int item_index,int itemID,char *str){
113 //メニューアイテムの挿入
114
115 CMenuItemData *pobj_MenuItemData;
116 pobj_MenuItemData=AddMenuExItemData(item_index,itemID,str,this,0);
117
118 MENUITEMINFO mii;
119 memset(&mii,0,sizeof(MENUITEMINFO));
120 mii.cbSize=sizeof(MENUITEMINFO);
121 mii.fMask=MIIM_TYPE|MIIM_ID|MIIM_DATA;
122 mii.fType=MFT_OWNERDRAW;
123 mii.wID=itemID;
124 mii.dwTypeData=str;
125 mii.dwItemData=(ULONG_PTR)pobj_MenuItemData;
126 InsertMenuItem(hMenu,item_index,1,&mii);
127}
128
129BOOL CMenuEx::SetIcon(int itemID,HICON hIcon){
130 //アイコンをセット
131 int i;
132 for(i=0;i<iMenuItemNum;i++){
133 if(ppobj_MenuItemData[i]->itemID==itemID){
134 ppobj_MenuItemData[i]->hIcon=hIcon;
135
136
137 /////////////////////////
138 // 淡色アイコンを作成
139 /////////////////////////
140
141 ppobj_MenuItemData[i]->hGrayIcon=CreateGrayIcon(hIcon);
142 return 1;
143 }
144 if(ppobj_MenuItemData[i]->pobj_SubMenu){
145 BOOL bResult;
146 bResult=ppobj_MenuItemData[i]->pobj_SubMenu->SetIcon(itemID,hIcon);
147 if(bResult) return 1;
148 }
149 }
150 return 0;
151}
152
153CMenuItemData *CMenuEx::AddMenuExItemData(int item_index,int itemID,char *str,CMenuEx *pobj_ThisMenu,CSubMenuEx *pobj_SubMenu){
154 CMenuItemData *pobj_MenuItemData;
155 pobj_MenuItemData=new CMenuItemData(item_index,itemID,str,pobj_ThisMenu,pobj_SubMenu);
156
157
158 ppobj_MenuItemData=(CMenuItemData **)HeapReAlloc(hHeap,0,ppobj_MenuItemData,(iMenuItemNum+1)*sizeof(CMenuItemData *));
159
160 int i;
161 for(i=iMenuItemNum;i>item_index;i--){
162 ppobj_MenuItemData[i]=ppobj_MenuItemData[i-1];
163 }
164
165 ppobj_MenuItemData[item_index]=pobj_MenuItemData;
166
167 iMenuItemNum++;
168
169 return pobj_MenuItemData;
170}
171void CMenuEx::InitOwnerDraw(BOOL bParent){
172 char temporary[MAX_PATH];
173 MENUITEMINFO mii;
174 mii.cbSize=sizeof(MENUITEMINFO);
175 mii.fMask=MIIM_TYPE|MIIM_ID|MIIM_SUBMENU|MIIM_DATA;
176
177 int nCount;
178 nCount=GetMenuItemCount(hMenu);
179
180 int i;
181 for(i=0;i<nCount;i++){
182 mii.dwTypeData=temporary;
183 mii.cch=MAX_PATH;
184 GetMenuItemInfo(hMenu,i,1,&mii);
185
186 char *temp2=0;
187 if(mii.fType==MFT_STRING) temp2=temporary;
188
189 int fType_Separator;
190 if(mii.fType==MFT_SEPARATOR) fType_Separator=MFT_SEPARATOR;
191 else fType_Separator=0;
192
193 CSubMenuEx *pobj_SubMenu;
194 if(mii.hSubMenu){
195 pobj_SubMenu=new CSubMenuEx(mii.hSubMenu);
196 pobj_SubMenu->InitOwnerDraw(0);
197 }
198 else pobj_SubMenu=0;
199
200 //拡張データをメモリに退避
201 CMenuItemData *pobj_MenuItemData;
202 pobj_MenuItemData=AddMenuExItemData(i,mii.wID,temp2,this,pobj_SubMenu);
203
204 mii.fType=MFT_OWNERDRAW | fType_Separator;
205 mii.dwItemData=(ULONG_PTR)pobj_MenuItemData;
206 SetMenuItemInfo(hMenu,i,1,&mii);
207 }
208}
209void CMenuEx::GetItemSize(int item_index,SIZE *pSize){
210 if(ppobj_MenuItemData[item_index]->str){
211 HDC hdc;
212 hdc = GetDC(GetDesktopWindow());
213 HFONT hOldFont;
214 hOldFont = (HFONT)SelectObject(hdc, hMenuFont);
215
216 GetTextExtentPoint32(hdc,
217 ppobj_MenuItemData[item_index]->str,
218 lstrlen(ppobj_MenuItemData[item_index]->str),
219 pSize);
220
221 SelectObject(hdc,hOldFont);
222 ReleaseDC(GetDesktopWindow(),hdc);
223 }
224 else{
225 //セパレータのとき
226 pSize->cx=50;
227 pSize->cy=10;
228 }
229}
230
231BOOL CMenuEx::OwnerDrawSubMenu(HMENU hSubMenu,HDC hdc,RECT *pRect,BOOL bSelect,int item_index){
232 int i;
233 for(i=0;i<iMenuItemNum;i++){
234 if(ppobj_MenuItemData[i]->pobj_SubMenu){
235 if(hSubMenu==ppobj_MenuItemData[i]->pobj_SubMenu->hMenu){
236 ppobj_MenuItemData[i]->pobj_SubMenu->OwnerDrawMenu(hdc,pRect,bSelect,item_index);
237 return 1;
238 }
239 else{
240 BOOL bResult;
241 bResult=ppobj_MenuItemData[i]->pobj_SubMenu->OwnerDrawSubMenu(hSubMenu,hdc,pRect,bSelect,item_index);
242 if(bResult) return 1;
243 }
244 }
245 }
246 return 0;
247}
248void CMenuEx::OwnerDrawMenu(HDC hdc,RECT *pRect,BOOL bSelect,int item_index){
249 /////////////////////////////////
250 // 親メニューのオーナー描画
251 /////////////////////////////////
252
253
254 COLORREF BackColor,TextColor;
255
256 RECT rc;
257
258 if(bSelect){
259 //選択状態にある場合
260 HPEN hPen,hOldPen;
261 hPen=CreatePen(PS_SOLID,0,MENUCOLOR_SELECT_LINE);
262 hOldPen=(HPEN)SelectObject(hdc,hPen);
263
264 HBRUSH hBrush,hOldBrush;
265 hBrush=CreateSolidBrush(MENUCOLOR_SELECT_BACK);
266 hOldBrush=(HBRUSH)SelectObject(hdc,hBrush);
267
268 pRect->left++;
269 pRect->top++;
270 Rectangle(hdc,pRect);
271 pRect->left--;
272
273 SelectObject(hdc,hOldPen);
274 SelectObject(hdc,hOldBrush);
275
276 DeleteObject(hPen);
277 DeleteObject(hBrush);
278
279 TextColor=MENUCOLOR_TEXT;
280 }
281 else{
282 POINT pos;
283 GetCursorPos(&pos);
284 GetWindowRect(hOwner,&rc);
285 pos.x-=rc.left;
286 pos.y-=rc.top;
287 if(HitTest(pRect,&pos)){
288 //ホットイメージで表示
289 HPEN hPen,hOldPen;
290 hPen=CreatePen(PS_SOLID,0,MENUCOLOR_HOT_LINE);
291 hOldPen=(HPEN)SelectObject(hdc,hPen);
292
293 HBRUSH hBrush,hOldBrush;
294 hBrush=CreateSolidBrush(MENUCOLOR_HOT_BACK);
295 hOldBrush=(HBRUSH)SelectObject(hdc,hBrush);
296
297 pRect->left++;
298 pRect->top++;
299 Rectangle(hdc,pRect);
300 pRect->left--;
301 pRect->top--;
302
303 SelectObject(hdc,hOldPen);
304 SelectObject(hdc,hOldBrush);
305
306 DeleteObject(hPen);
307 DeleteObject(hBrush);
308
309 TextColor=MENUCOLOR_TEXT;
310 }
311 else{
312 BackColor=MENUCOLOR_DEFAULT_BACK;
313 TextColor=MENUCOLOR_TEXT;
314
315 //背景を塗りつぶす
316 HBRUSH hBrush;
317 hBrush=CreateSolidBrush(BackColor);
318 FillRect(hdc,pRect,hBrush);
319 DeleteObject(hBrush);
320 }
321 }
322
323
324 if(ppobj_MenuItemData[item_index]->str){
325 rc=*pRect;
326 rc.top+=1;
327
328 SetBkMode(hdc, TRANSPARENT);
329 SetTextColor(hdc, TextColor);
330
331 HFONT hOldFont;
332 hOldFont=(HFONT)SelectObject(hdc,hMenuFont);
333
334 DrawText(hdc,ppobj_MenuItemData[item_index]->str,-1,&rc,DT_CENTER|DT_VCENTER|DT_SINGLELINE);
335
336 SelectObject(hdc,hOldFont);
337 }
338 else{
339 //セパレータのとき
340 }
341}
342
343
344CSubMenuEx::CSubMenuEx(HMENU hMenu):CMenuEx(hMenu){
345}
346void CSubMenuEx::GetItemSize(int item_index,SIZE *pSize){
347 if(ppobj_MenuItemData[item_index]->str){
348 HDC hdc;
349 hdc = GetDC(GetDesktopWindow());
350 HFONT hOldFont;
351 hOldFont = (HFONT)SelectObject(hdc, hMenuFont);
352
353 GetTextExtentPoint32(hdc,
354 ppobj_MenuItemData[item_index]->str,
355 lstrlen(ppobj_MenuItemData[item_index]->str),
356 pSize);
357
358 SelectObject(hdc,hOldFont);
359 ReleaseDC(GetDesktopWindow(),hdc);
360
361 pSize->cx+=50;
362 if(pSize->cy<22) pSize->cy=22;
363 }
364 else{
365 //セパレータのとき
366 pSize->cx=50;
367 pSize->cy=10;
368 }
369}
370
371void CSubMenuEx::OwnerDrawMenu(HDC hdc,RECT *pRect,BOOL bSelect,int item_index){
372 //////////////////////////////////
373 // サブメニューのオーナー描画
374 //////////////////////////////////
375
376 RECT rc;
377 COLORREF BackColor,TextColor;
378 int i;
379
380 ///////////////////////////////
381 // 左側のグラデーションを描画
382 ///////////////////////////////
383
384 SIZE size;
385 size.cx=22;
386 size.cy=pRect->bottom-pRect->top;
387 HBITMAP hBmp;
388 hBmp=CreateHorzGradationBitmap(&size,RGB(254,254,251),RGB(196,196,173));
389
390 HDC memdc;
391 memdc=CreateCompatibleDC(hdc);
392 SelectObject(memdc,hBmp);
393 BitBlt(hdc,pRect->left,pRect->top,size.cx,size.cy,memdc,0,0,SRCCOPY);
394 DeleteDC(memdc);
395 DeleteObject(hBmp);
396
397
398 if(ppobj_MenuItemData[item_index]->str==0){
399 //セパレータのとき
400 HPEN hPen,hOldPen;
401 hPen=CreatePen(PS_SOLID,0,MENUCOLOR_DEFAULT_LINE);
402 hOldPen=(HPEN)SelectObject(hdc,hPen);
403
404 MoveToEx(hdc,pRect->left+24,pRect->top+(pRect->bottom-pRect->top)/2,NULL);
405 LineTo(hdc,pRect->right,pRect->top+(pRect->bottom-pRect->top)/2);
406
407 SelectObject(hdc,hOldPen);
408 DeleteObject(hPen);
409 return;
410 }
411
412
413 //アイテムの状態を取得
414 MENUITEMINFO mii;
415 mii.cbSize=sizeof(MENUITEMINFO);
416 mii.fMask=MIIM_STATE;
417 GetMenuItemInfo(hMenu,item_index,1,&mii);
418
419
420 if(bSelect&&(mii.fState&MFS_DISABLED)==0){
421 //ホットイメージで表示
422 BackColor=MENUCOLOR_HOT_BACK;
423
424 HPEN hPen,hOldPen;
425 hPen=CreatePen(PS_SOLID,0,MENUCOLOR_HOT_LINE);
426 hOldPen=(HPEN)SelectObject(hdc,hPen);
427
428 HBRUSH hBrush,hOldBrush;
429 hBrush=CreateSolidBrush(BackColor);
430 hOldBrush=(HBRUSH)SelectObject(hdc,hBrush);
431
432 Rectangle(hdc,pRect);
433
434 SelectObject(hdc,hOldPen);
435 SelectObject(hdc,hOldBrush);
436
437 DeleteObject(hPen);
438 DeleteObject(hBrush);
439 }
440 else{
441 //マウスカーソルの座標を取得
442 POINT pos;
443 GetCursorPos(&pos);
444
445 //親ウィンドウのウィンドウ左上からの相対座標に変換
446 //(クライアント座標ではないところに注意)
447 GetWindowRect(WindowFromDC(hdc),&rc);
448 ScreenToClient(WindowFromDC(hdc),&pos);
449
450 if(bSelect&&HitTest(pRect,&pos)==0){
451 //淡色状態
452 BackColor=MENUCOLOR_SELECT_BACK;
453
454 HPEN hPen,hOldPen;
455 hPen=CreatePen(PS_SOLID,0,MENUCOLOR_SELECT_LINE);
456 hOldPen=(HPEN)SelectObject(hdc,hPen);
457
458 HBRUSH hBrush,hOldBrush;
459 hBrush=CreateSolidBrush(BackColor);
460 hOldBrush=(HBRUSH)SelectObject(hdc,hBrush);
461
462 Rectangle(hdc,pRect);
463
464 SelectObject(hdc,hOldPen);
465 SelectObject(hdc,hOldBrush);
466
467 DeleteObject(hPen);
468 DeleteObject(hBrush);
469 }
470 else{
471 BackColor=GetSysColor(COLOR_MENU);
472
473 rc=*pRect;
474 rc.left=pRect->left+22;
475 rc.right=pRect->right;
476
477 //背景を塗りつぶす
478 HBRUSH hBrush;
479 hBrush=CreateSolidBrush(BackColor);
480 FillRect(hdc,&rc,hBrush);
481 DeleteObject(hBrush);
482 }
483 }
484
485
486 if(mii.fState&MFS_CHECKED){
487 //チェックマークの外枠を描画
488 rc=*pRect;
489 rc.top++;
490 rc.right=rc.left+20;
491 rc.bottom--;
492
493 HPEN hPen,hOldPen;
494 hPen=CreatePen(PS_SOLID,0,MENUCOLOR_HOT_LINE);
495 hOldPen=(HPEN)SelectObject(hdc,hPen);
496
497 HBRUSH hBrush,hOldBrush;
498 hBrush=CreateSolidBrush(BackColor);
499 hOldBrush=(HBRUSH)SelectObject(hdc,hBrush);
500
501 Rectangle(hdc,&rc);
502
503 SelectObject(hdc,hOldPen);
504 SelectObject(hdc,hOldBrush);
505
506 DeleteObject(hPen);
507 DeleteObject(hBrush);
508
509
510 //チェックマークを描画
511 int BaseX=rc.left,BaseY=rc.top;
512 for(i=0;i<3;i++){
513 SetPixel(hdc,BaseX+6+i,BaseY+9+i,MENUCOLOR_TEXT);
514 SetPixel(hdc,BaseX+6+i,BaseY+10+i,MENUCOLOR_TEXT);
515 }
516 for(i=0;i<4;i++){
517 SetPixel(hdc,BaseX+9+i,BaseY+10-i,MENUCOLOR_TEXT);
518 SetPixel(hdc,BaseX+9+i,BaseY+11-i,MENUCOLOR_TEXT);
519 }
520 }
521 else{
522 if(ppobj_MenuItemData[item_index]->hIcon){
523 //アイコンを描画
524 HICON hIcon;
525 if(mii.fState&MFS_DISABLED) hIcon=ppobj_MenuItemData[item_index]->hGrayIcon;
526 else hIcon=ppobj_MenuItemData[item_index]->hIcon;
527
528 DrawIconEx(hdc,pRect->left+1,pRect->top+3,hIcon,16,16,0,NULL,DI_NORMAL);
529 }
530 }
531
532
533
534 //メイン文字列とショートカットキー文字列を分別
535 char szMain[255],szShortcut[255];
536 for(i=0;;i++){
537 if(ppobj_MenuItemData[item_index]->str[i]=='\t'){
538 szMain[i]=0;
539
540 lstrcpy(szShortcut,ppobj_MenuItemData[item_index]->str+i+1);
541 break;
542 }
543 szMain[i]=ppobj_MenuItemData[item_index]->str[i];
544 if(ppobj_MenuItemData[item_index]->str[i]=='\0'){
545 szShortcut[0]=0;
546 break;
547 }
548 }
549
550 rc=*pRect;
551 rc.left=pRect->left+26;
552 rc.right=pRect->right;
553
554 HFONT hOldFont;
555 hOldFont=(HFONT)SelectObject(hdc,hMenuFont);
556
557 if(mii.fState&MFS_DISABLED){
558 //淡色カラー
559 TextColor=MENUCOLOR_GRAY_TEXT;
560 }
561 else{
562 //通常カラー
563 TextColor=MENUCOLOR_TEXT;
564 }
565
566 SetBkMode(hdc, TRANSPARENT);
567 SetTextColor(hdc, TextColor);
568
569 DrawText(hdc,szMain,-1,&rc,DT_VCENTER|DT_LEFT|DT_SINGLELINE);
570
571 if(szShortcut[0]){
572 rc.left=rc.right-45;
573 DrawText(hdc,szShortcut,-1,&rc,DT_VCENTER|DT_LEFT|DT_SINGLELINE);
574 }
575
576 SelectObject(hdc,hOldFont);
577}
Note: See TracBrowser for help on using the repository browser.