home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 2002 December (Special) / DOSV2002_12.iso / utility / tcl230ja95.lzh / source.lzh / dll / startmenu.c < prev    next >
C/C++ Source or Header  |  2001-01-29  |  11KB  |  416 lines

  1. /*-------------------------------------------
  2.   startmenu.c
  3.     customize start menu
  4.     Kazubon 1997-1999
  5. ---------------------------------------------*/
  6.  
  7. #include "tcdll.h"
  8.  
  9. static void OnDrawItem(HWND hwnd, DRAWITEMSTRUCT* pdis);
  10. static BOOL IsStartMenu(HMENU hmenu);
  11. void DeleteStartMenuRes(void);
  12.  
  13. /*------------------------------------------------
  14.  Globals
  15. --------------------------------------------------*/
  16. static BOOL bStartMenu = FALSE;
  17. static HWND hwndBar = NULL;           // タスクバーのウィンドウハンドル
  18. static WNDPROC oldWndProcBar = NULL;  // ウィンドウプロシージャを保存
  19. static HDC hdcMemMenu = NULL;         // メニュー描画用メモリDC
  20. static HBITMAP hbmpMenu = NULL;       // メニュー描画用ビットマップ
  21. static HDC hdcMemMenuLeft = NULL;     // 「Windows95」部分用メモリDC
  22. static HBITMAP hbmpMenuLeft = NULL;   // 「Windows95」部分用ビットマップ
  23. static int hStartMenu = 0;            // メニューの高さを保存
  24. static COLORREF colMenuLeft;          // 色
  25. static BOOL bTile = FALSE;     // 並べる
  26.  
  27. /*------------------------------------------------
  28.  タスクバーのサブクラスプロシージャ
  29. --------------------------------------------------*/
  30. LRESULT CALLBACK WndProcBar(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  31. {
  32.     switch(message)
  33.     {
  34.         // メニューのオーナードロー
  35.         case WM_DRAWITEM:
  36.         {
  37.             DRAWITEMSTRUCT* pdis;
  38.             
  39.             if(!bStartMenu) break;
  40.             pdis = (DRAWITEMSTRUCT*)lParam;
  41.             // スタートメニューでなかったらそのまま
  42.             if(wParam || !IsStartMenu((HMENU)pdis->hwndItem)) break;
  43.             OnDrawItem(hwnd, pdis);
  44.             return 1;
  45.         }
  46.         // システム色変更
  47.         case WM_SYSCOLORCHANGE:
  48.             if(hdcMemMenu) DeleteDC(hdcMemMenu); hdcMemMenu = NULL;
  49.             if(hbmpMenu) DeleteObject(hbmpMenu); hbmpMenu = NULL;
  50.             break;
  51.         // v1.7  タスクバーの表示が乱れるのを防ぐ
  52.         case WM_EXITSIZEMOVE:
  53.             PostMessage(hwnd, WM_SIZE, SIZE_RESTORED, 0);
  54.             break;
  55.         
  56.         case WM_DESTROY:
  57.             DeleteStartMenuRes();
  58.             break;
  59.     }
  60.     return CallWindowProc(oldWndProcBar, hwnd, message, wParam, lParam);
  61. }
  62.  
  63. /*------------------------------------------------
  64.  メニューのオーナードロー
  65. --------------------------------------------------*/
  66. void OnDrawItem(HWND hwnd, DRAWITEMSTRUCT* pdis)
  67. {
  68.     HDC hdc;
  69.     RECT rcBox, rcItem;
  70.     HBRUSH hbr;
  71.     BITMAP bmp;
  72.  
  73.     hdc = pdis->hDC;
  74.     CopyRect(&rcItem, &(pdis->rcItem));
  75.     GetClipBox(hdc, &rcBox); // メニュー全体の大きさ
  76.  
  77.     // 描画用メモリDCとビットマップの作成
  78.     if(hdcMemMenu == NULL ||
  79.         (hStartMenu != rcBox.bottom && rcBox.left == 0))
  80.     {
  81.         if(hdcMemMenu) DeleteDC(hdcMemMenu);
  82.         if(hbmpMenu) DeleteObject(hbmpMenu);
  83.                 
  84.         hdcMemMenu = CreateCompatibleDC(hdc);
  85.         hbmpMenu = CreateCompatibleBitmap(hdc, rcBox.right, rcBox.bottom);
  86.         SelectObject(hdcMemMenu, hbmpMenu);
  87.         hbr = CreateSolidBrush(GetSysColor(COLOR_MENU));
  88.         FillRect(hdcMemMenu, &rcBox, hbr);
  89.         hStartMenu = rcBox.bottom;
  90.     }
  91.     
  92.     SelectObject(hdcMemMenu, (HFONT)GetCurrentObject(hdc, OBJ_FONT));
  93.     
  94.     // 背景色、文字色の設定
  95.     if(pdis->itemState & ODS_FOCUS)
  96.     {
  97.         SetTextColor(hdcMemMenu, GetSysColor(COLOR_HIGHLIGHTTEXT));
  98.         SetBkColor(hdcMemMenu, GetSysColor(COLOR_HIGHLIGHT));
  99.     }
  100.     else
  101.     {
  102.         SetTextColor(hdcMemMenu, GetSysColor(COLOR_MENUTEXT));
  103.         SetBkColor(hdcMemMenu, GetSysColor(COLOR_MENU));
  104.     }
  105.     
  106.     // メモリDCにデフォルトの描画をさせる
  107.     pdis->hDC = hdcMemMenu;
  108.     CallWindowProc(oldWndProcBar, hwnd, WM_DRAWITEM, 0, (LPARAM)pdis);
  109.     
  110.     // 「Windows95」の幅が、pdis->rcItem.leftに入ってくる
  111.     rcItem.right = pdis->rcItem.left;
  112.     
  113.     if(rcItem.right > 0)
  114.     {
  115.         COLORREF col;
  116.         
  117.         if(!bTile)
  118.         {
  119.             //「色」で塗りつぶし
  120.             col = colMenuLeft;
  121.             if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  122.             hbr = CreateSolidBrush(col);
  123.             FillRect(hdcMemMenu, &rcItem, hbr);
  124.             DeleteObject(hbr);
  125.         }
  126.         
  127.         if(hbmpMenuLeft)
  128.             GetObject(hbmpMenuLeft, sizeof(BITMAP), &bmp);
  129.         
  130.         if(hbmpMenuLeft) 
  131.         // && rcItem.bottom > rcBox.bottom - bmp.bmHeight)
  132.         {
  133.             int i, j;
  134.             // ビットマップ描画
  135.             for(i = 0; ; i++)
  136.             {
  137.                 int y, ysrc, h, x, w;
  138.                 for(j = 0; ; j++)
  139.                 {
  140.                     y = rcBox.bottom - ((i + 1) * bmp.bmHeight);
  141.                     ysrc = 0;
  142.                     h = bmp.bmHeight;
  143.                     if(y < 0)
  144.                     {
  145.                         y = 0;
  146.                         ysrc = ((i + 1) * bmp.bmHeight) - rcBox.bottom;
  147.                         h -= ysrc;
  148.                     }
  149.                     x = j * bmp.bmWidth; w = bmp.bmWidth;
  150.                     if(x + w > rcItem.right)
  151.                     {
  152.                         w -= ((j + 1) * bmp.bmWidth) - rcItem.right;
  153.                     }
  154.                     if(w > 0 && h > 0)
  155.                         BitBlt(hdcMemMenu, x, y, w, h,
  156.                             hdcMemMenuLeft, 0, ysrc, SRCCOPY);
  157.                     if(!bTile || w < bmp.bmWidth) break;
  158.                 }
  159.                 if(!bTile || y == 0) break;
  160.             }
  161.         }
  162.     }
  163.  
  164.     // 本当のDCにまとめて描画
  165.     BitBlt(hdc, 0, rcItem.top,
  166.         pdis->rcItem.right, rcItem.bottom - rcItem.top,
  167.         hdcMemMenu, 0, rcItem.top, SRCCOPY);
  168.     pdis->hDC = hdc;
  169. }
  170.  
  171. /*--------------------------------------------------
  172.  スタートメニュー改造の初期化
  173. ----------------------------------------------------*/
  174. void SetStartMenu(HWND hwndClock)
  175. {
  176.     HWND hwndTray;
  177.     
  178.     char fname[1024];
  179.     
  180.     EndStartMenu();
  181.     
  182.     // タスクバーのサブクラス化(v1.7より必ずサブクラス化)
  183.     hwndTray = GetParent(hwndClock); // TrayNotifyWnd
  184.     if(hwndTray == NULL)
  185.         return;
  186.     hwndBar = GetParent(hwndTray);   // Shell_TrayWnd
  187.     if(hwndBar == NULL)
  188.         return;
  189.     oldWndProcBar = (WNDPROC)GetWindowLong(hwndBar, GWL_WNDPROC);
  190.     SetWindowLong(hwndBar, GWL_WNDPROC, (LONG)WndProcBar);
  191.     
  192.     bStartMenu = GetMyRegLong(NULL, "StartMenu", FALSE);
  193.     
  194.     if(!bStartMenu) return;
  195.     
  196.     colMenuLeft = GetMyRegLong(NULL, "StartMenuCol",
  197.         RGB(128, 128, 128));
  198.     
  199.     bTile = GetMyRegLong(NULL, "StartMenuTile", FALSE);
  200.     
  201.     GetMyRegStr(NULL, "StartMenuBmp", fname, 1024, "");
  202.     
  203.     if(fname[0]) // 「Windows95」部分用のメモリDCとビットマップ作成
  204.     {
  205.         hbmpMenuLeft = ReadBitmap(hwndBar, fname, FALSE);
  206.         if(hbmpMenuLeft)
  207.         {
  208.             HDC hdc;
  209.             hdc = GetDC(hwndBar);
  210.             hdcMemMenuLeft = CreateCompatibleDC(hdc);
  211.             SelectObject(hdcMemMenuLeft, hbmpMenuLeft);
  212.             ReleaseDC(hwndBar, hdc);
  213.         }
  214.     }
  215. }
  216.  
  217. /*--------------------------------------------------
  218.  元に戻す
  219. ----------------------------------------------------*/
  220. void DeleteStartMenuRes(void)
  221. {
  222.     if(hdcMemMenu) DeleteDC(hdcMemMenu); hdcMemMenu = NULL;
  223.     if(hbmpMenu) DeleteObject(hbmpMenu); hbmpMenu = NULL;
  224.     if(hdcMemMenuLeft) DeleteDC(hdcMemMenuLeft); hdcMemMenuLeft = NULL;
  225.     if(hbmpMenuLeft) DeleteObject(hbmpMenuLeft); hbmpMenuLeft = NULL;
  226. }
  227. void EndStartMenu(void)
  228. {
  229.     if(hwndBar && IsWindow(hwndBar) && oldWndProcBar)
  230.         SetWindowLong(hwndBar, GWL_WNDPROC, (LONG)oldWndProcBar);
  231.     hwndBar = NULL; oldWndProcBar = NULL;
  232.     
  233.     DeleteStartMenuRes();
  234. }
  235.  
  236. /*--------------------------------------------------
  237.  スタートメニューかどうか判別
  238. ----------------------------------------------------*/
  239. BOOL IsStartMenu(HMENU hmenu)
  240. {
  241.     int i, count, id;
  242.     
  243.     count = GetMenuItemCount(hmenu);
  244.     for(i = 0; i < count; i++)
  245.     {
  246.         id = GetMenuItemID(hmenu, i);
  247.         // 「ヘルプ」があればスタートメニュー
  248.         if(id == 503) return TRUE;
  249.     }
  250.     return FALSE;
  251. }
  252.  
  253. // ------------------------------------------------------
  254. // 以下、IE4用
  255.  
  256. LRESULT CALLBACK WndProcStartMenu(HWND hwnd, UINT message,
  257.     WPARAM wParam, LPARAM lParam);
  258. HWND hwndStartMenu = NULL; // スタートメニューのウィンドウハンドル
  259. WNDPROC oldWndProcStartMenu = NULL;
  260. void OnPaintStartmenuIE4(HWND hwnd, HDC hdc, BOOL bPrint);
  261.  
  262. /*--------------------------------------------------
  263.  スタートメニューウィンドウのサブクラス化
  264. ----------------------------------------------------*/
  265. void InitStartMenuIE4(void)
  266. {
  267.     HWND hwnd, hwndChild;
  268.     HWND hwndFound;
  269.     char classname[80];
  270.     RECT rc1, rc2;
  271.     
  272.     // スタートメニューを探す
  273.     hwnd = GetDesktopWindow();
  274.     hwnd = GetWindow(hwnd, GW_CHILD);
  275.     hwndFound = NULL;
  276.     while(hwnd)
  277.     {
  278.         GetClassName(hwnd, classname, 80);
  279.         if(lstrcmpi(classname, "BaseBar") == 0)
  280.         {
  281.             if(GetWindowThreadProcessId(hwnd, NULL) ==
  282.                 GetCurrentThreadId())
  283.             {
  284.                 hwndChild = GetWindow(hwnd, GW_CHILD);
  285.                 GetClientRect(hwnd, &rc1);
  286.                 GetClientRect(hwndChild, &rc2);
  287.                 if(rc1.right - rc2.right == 21 || rc2.right == 0)
  288.                 {
  289.                     if(hwndFound == NULL
  290.                         || (int)hwndFound > (int)hwnd)
  291.                         hwndFound = hwnd;
  292.                 }
  293.             }
  294.         }
  295.         hwnd = GetWindow(hwnd, GW_HWNDNEXT);
  296.     }
  297.     hwnd = hwndFound;
  298.     if(hwnd == NULL) return;
  299.     // サブクラス化
  300.     oldWndProcStartMenu = (WNDPROC)GetWindowLong(hwnd, GWL_WNDPROC);
  301.     SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndProcStartMenu);
  302.     hwndStartMenu = hwnd;
  303. }
  304.  
  305. /*--------------------------------------------------
  306.  スタートメニューウィンドウを元に戻す
  307. ----------------------------------------------------*/
  308. void ClearStartMenuIE4(void)
  309. {
  310.     if(hwndStartMenu && IsWindow(hwndStartMenu) && oldWndProcStartMenu)
  311.         SetWindowLong(hwndStartMenu, GWL_WNDPROC, (LONG)oldWndProcStartMenu);
  312.     hwndStartMenu = NULL; oldWndProcStartMenu = NULL;
  313. }
  314.  
  315. /*------------------------------------------------
  316.  スタートメニューのサブクラスプロシージャ
  317. --------------------------------------------------*/
  318. LRESULT CALLBACK WndProcStartMenu(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  319. {
  320.     switch(message)
  321.     {
  322.         // メニューの描画
  323.         case WM_PAINT:
  324.         {
  325.             PAINTSTRUCT ps;
  326.             HDC hdc;
  327.             if(!bStartMenu) break;
  328.             hdc = BeginPaint(hwnd, &ps);
  329.             OnPaintStartmenuIE4(hwnd, hdc, FALSE);
  330.             EndPaint(hwnd, &ps);
  331.             return 0;
  332.         }
  333.         case WM_PRINT:
  334.         {
  335.             LRESULT r;
  336.             if(!bStartMenu) break;
  337.             r = CallWindowProc(oldWndProcStartMenu, hwnd, message, wParam, lParam);
  338.             OnPaintStartmenuIE4(hwnd, (HDC)wParam, TRUE);
  339.             return r;
  340.         }
  341.         // システム色変更
  342.         case WM_SYSCOLORCHANGE:
  343.             break;
  344.     }
  345.     return CallWindowProc(oldWndProcStartMenu, hwnd, message, wParam, lParam);
  346. }
  347.  
  348. /*------------------------------------------------
  349.  スタートメニューの描画
  350. --------------------------------------------------*/
  351. void OnPaintStartmenuIE4(HWND hwnd, HDC hdc, BOOL bPrint)
  352. {
  353.     RECT rc, rcWin, rcChild;
  354.     POINT pt;
  355.     COLORREF col;
  356.     HBRUSH hbr;
  357.     BITMAP bmp;
  358.     int hClient, wClient;
  359.     
  360.     GetWindowRect(GetWindow(hwnd, GW_CHILD), &rcChild);
  361.     GetWindowRect(hwnd, &rcWin);
  362.     GetClientRect(hwnd, &rc);
  363.     pt.x = 0; pt.y = 0;
  364.     ClientToScreen(hwnd, &pt);
  365.     if(pt.x == rcChild.left) return;
  366.     
  367.     rc.right = 21;
  368.     wClient = rc.right; hClient = rc.bottom;
  369.     if(bPrint)
  370.     {
  371.         int dx, dy;
  372.         dx = pt.x - rcWin.left; dy = pt.y - rcWin.top;
  373.         rc.left += dx; rc.right += dx;
  374.         rc.top += dy; rc.bottom += dy;
  375.     }
  376.     //「色」で塗りつぶし
  377.     col = colMenuLeft;
  378.     if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  379.     hbr = CreateSolidBrush(col);
  380.     FillRect(hdc, &rc, hbr);
  381.     DeleteObject(hbr);
  382.     if(hbmpMenuLeft)
  383.     {
  384.         int i, j;
  385.         GetObject(hbmpMenuLeft, sizeof(BITMAP), &bmp);
  386.         // ビットマップ描画
  387.         for(i = 0; ; i++)
  388.         {
  389.             int y, ysrc, h, x, w;
  390.             for(j = 0; ; j++)
  391.             {
  392.                 y = hClient - ((i + 1) * bmp.bmHeight);
  393.                 ysrc = 0;
  394.                 h = bmp.bmHeight;
  395.                 if(y < 0)
  396.                 {
  397.                     y = 0;
  398.                     ysrc = ((i + 1) * bmp.bmHeight) - hClient;
  399.                     h -= ysrc;
  400.                 }
  401.                 x = j * bmp.bmWidth; w = bmp.bmWidth;
  402.                 if(x + w > wClient)
  403.                 {
  404.                     w -= ((j + 1) * bmp.bmWidth) - wClient;
  405.                 }
  406.                 if(w > 0 && h > 0)
  407.                     BitBlt(hdc, rc.left + x, rc.top + y, w, h,
  408.                         hdcMemMenuLeft, 0, ysrc, SRCCOPY);
  409.                 if(!bTile || w < bmp.bmWidth) break;
  410.             }
  411.             if(!bTile || y == 0) break;
  412.         }
  413.     }
  414. }
  415.  
  416.