home *** CD-ROM | disk | FTP | other *** search
/ DOS/V Power Report 2001 June / VPR0106A.BIN / OLS / TCL228 / TCL228.lzh / DLLSRC.lzh / startmenu.c < prev    next >
C/C++ Source or Header  |  1999-09-18  |  11KB  |  410 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. BOOL bStartMenu = FALSE;
  17. HWND hwndBar = NULL;           // タスクバーのウィンドウハンドル
  18. WNDPROC oldWndProcBar = NULL;  // ウィンドウプロシージャを保存
  19. HDC hdcMemMenu = NULL;         // メニュー描画用メモリDC
  20. HBITMAP hbmpMenu = NULL;       // メニュー描画用ビットマップ
  21. HDC hdcMemMenuLeft = NULL;     // 「Windows95」部分用メモリDC
  22. HBITMAP hbmpMenuLeft = NULL;   // 「Windows95」部分用ビットマップ
  23. int hStartMenu = 0;            // メニューの高さを保存
  24. 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.     char fname[1024];
  177.  
  178.     EndStartMenu();
  179.     
  180.     // タスクバーのサブクラス化(v1.7より必ずサブクラス化)
  181.     hwndBar = GetParent(GetParent(hwndClock)); // Shell_TrayWnd
  182.     oldWndProcBar = (WNDPROC)GetWindowLong(hwndBar, GWL_WNDPROC);
  183.     SetWindowLong(hwndBar, GWL_WNDPROC, (LONG)WndProcBar);
  184.     
  185.     bStartMenu = GetMyRegLong(NULL, "StartMenu", FALSE);
  186.     
  187.     if(!bStartMenu) return;
  188.     
  189.     colMenuLeft = GetMyRegLong(NULL, "StartMenuCol",
  190.         RGB(128, 128, 128));
  191.     
  192.     bTile = GetMyRegLong(NULL, "StartMenuTile", FALSE);
  193.     
  194.     GetMyRegStr(NULL, "StartMenuBmp", fname, 1024, "");
  195.     
  196.     if(fname[0]) // 「Windows95」部分用のメモリDCとビットマップ作成
  197.     {
  198.         hbmpMenuLeft = ReadBitmap(hwndBar, fname, FALSE);
  199.         if(hbmpMenuLeft)
  200.         {
  201.             HDC hdc;
  202.             hdc = GetDC(hwndBar);
  203.             hdcMemMenuLeft = CreateCompatibleDC(hdc);
  204.             SelectObject(hdcMemMenuLeft, hbmpMenuLeft);
  205.             ReleaseDC(hwndBar, hdc);
  206.         }
  207.     }
  208. }
  209.  
  210. /*--------------------------------------------------
  211.  元に戻す
  212. ----------------------------------------------------*/
  213. void DeleteStartMenuRes(void)
  214. {
  215.     if(hdcMemMenu) DeleteDC(hdcMemMenu); hdcMemMenu = NULL;
  216.     if(hbmpMenu) DeleteObject(hbmpMenu); hbmpMenu = NULL;
  217.     if(hdcMemMenuLeft) DeleteDC(hdcMemMenuLeft); hdcMemMenuLeft = NULL;
  218.     if(hbmpMenuLeft) DeleteObject(hbmpMenuLeft); hbmpMenuLeft = NULL;
  219. }
  220. void EndStartMenu(void)
  221. {
  222.     if(hwndBar && IsWindow(hwndBar) && oldWndProcBar)
  223.         SetWindowLong(hwndBar, GWL_WNDPROC, (LONG)oldWndProcBar);
  224.     hwndBar = NULL; oldWndProcBar = NULL;
  225.     
  226.     DeleteStartMenuRes();
  227. }
  228.  
  229. /*--------------------------------------------------
  230.  スタートメニューかどうか判別
  231. ----------------------------------------------------*/
  232. BOOL IsStartMenu(HMENU hmenu)
  233. {
  234.     int i, count, id;
  235.     
  236.     count = GetMenuItemCount(hmenu);
  237.     for(i = 0; i < count; i++)
  238.     {
  239.         id = GetMenuItemID(hmenu, i);
  240.         // 「ヘルプ」があればスタートメニュー
  241.         if(id == 503) return TRUE;
  242.     }
  243.     return FALSE;
  244. }
  245.  
  246. // ------------------------------------------------------
  247. // 以下、IE4用
  248.  
  249. LRESULT CALLBACK WndProcStartMenu(HWND hwnd, UINT message,
  250.     WPARAM wParam, LPARAM lParam);
  251. HWND hwndStartMenu = NULL; // スタートメニューのウィンドウハンドル
  252. WNDPROC oldWndProcStartMenu = NULL;
  253. void OnPaintStartmenuIE4(HWND hwnd, HDC hdc, BOOL bPrint);
  254.  
  255. /*--------------------------------------------------
  256.  スタートメニューウィンドウのサブクラス化
  257. ----------------------------------------------------*/
  258. void InitStartMenuIE4(void)
  259. {
  260.     HWND hwnd, hwndChild;
  261.     HWND hwndFound;
  262.     char classname[80];
  263.     RECT rc1, rc2;
  264.     
  265.     // スタートメニューを探す
  266.     hwnd = GetDesktopWindow();
  267.     hwnd = GetWindow(hwnd, GW_CHILD);
  268.     hwndFound = NULL;
  269.     while(hwnd)
  270.     {
  271.         GetClassName(hwnd, classname, 80);
  272.         if(lstrcmpi(classname, "BaseBar") == 0)
  273.         {
  274.             if(GetWindowThreadProcessId(hwnd, NULL) ==
  275.                 GetCurrentThreadId())
  276.             {
  277.                 hwndChild = GetWindow(hwnd, GW_CHILD);
  278.                 GetClientRect(hwnd, &rc1);
  279.                 GetClientRect(hwndChild, &rc2);
  280.                 if(rc1.right - rc2.right == 21 || rc2.right == 0)
  281.                 {
  282.                     if(hwndFound == NULL
  283.                         || (int)hwndFound > (int)hwnd)
  284.                         hwndFound = hwnd;
  285.                 }
  286.             }
  287.         }
  288.         hwnd = GetWindow(hwnd, GW_HWNDNEXT);
  289.     }
  290.     hwnd = hwndFound;
  291.     if(hwnd == NULL) return;
  292.     
  293.     // サブクラス化
  294.     oldWndProcStartMenu = (WNDPROC)GetWindowLong(hwnd, GWL_WNDPROC);
  295.     SetWindowLong(hwnd, GWL_WNDPROC, (LONG)WndProcStartMenu);
  296.     hwndStartMenu = hwnd;
  297. }
  298.  
  299. /*--------------------------------------------------
  300.  スタートメニューウィンドウを元に戻す
  301. ----------------------------------------------------*/
  302. void ClearStartMenuIE4(void)
  303. {
  304.     if(hwndStartMenu && IsWindow(hwndStartMenu) && oldWndProcStartMenu)
  305.         SetWindowLong(hwndStartMenu, GWL_WNDPROC, (LONG)oldWndProcStartMenu);
  306.     hwndStartMenu = NULL; oldWndProcStartMenu = NULL;
  307. }
  308.  
  309. /*------------------------------------------------
  310.  スタートメニューのサブクラスプロシージャ
  311. --------------------------------------------------*/
  312. LRESULT CALLBACK WndProcStartMenu(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
  313. {
  314.     switch(message)
  315.     {
  316.         // メニューの描画
  317.         case WM_PAINT:
  318.         {
  319.             PAINTSTRUCT ps;
  320.             HDC hdc;
  321.             if(!bStartMenu) break;
  322.             hdc = BeginPaint(hwnd, &ps);
  323.             OnPaintStartmenuIE4(hwnd, hdc, FALSE);
  324.             EndPaint(hwnd, &ps);
  325.             return 0;
  326.         }
  327.         case WM_PRINT:
  328.         {
  329.             LRESULT r;
  330.             if(!bStartMenu) break;
  331.             r = CallWindowProc(oldWndProcStartMenu, hwnd, message, wParam, lParam);
  332.             OnPaintStartmenuIE4(hwnd, (HDC)wParam, TRUE);
  333.             return r;
  334.         }
  335.         // システム色変更
  336.         case WM_SYSCOLORCHANGE:
  337.             break;
  338.     }
  339.     return CallWindowProc(oldWndProcStartMenu, hwnd, message, wParam, lParam);
  340. }
  341.  
  342. /*------------------------------------------------
  343.  スタートメニューの描画
  344. --------------------------------------------------*/
  345. void OnPaintStartmenuIE4(HWND hwnd, HDC hdc, BOOL bPrint)
  346. {
  347.     RECT rc, rcWin, rcChild;
  348.     POINT pt;
  349.     COLORREF col;
  350.     HBRUSH hbr;
  351.     BITMAP bmp;
  352.     int hClient, wClient;
  353.     
  354.     GetWindowRect(GetWindow(hwnd, GW_CHILD), &rcChild);
  355.     GetWindowRect(hwnd, &rcWin);
  356.     GetClientRect(hwnd, &rc);
  357.     pt.x = 0; pt.y = 0;
  358.     ClientToScreen(hwnd, &pt);
  359.     if(pt.x == rcChild.left) return;
  360.     
  361.     rc.right = 21;
  362.     wClient = rc.right; hClient = rc.bottom;
  363.     if(bPrint)
  364.     {
  365.         int dx, dy;
  366.         dx = pt.x - rcWin.left; dy = pt.y - rcWin.top;
  367.         rc.left += dx; rc.right += dx;
  368.         rc.top += dy; rc.bottom += dy;
  369.     }
  370.     //「色」で塗りつぶし
  371.     col = colMenuLeft;
  372.     if(col & 0x80000000) col = GetSysColor(col & 0x00ffffff);
  373.     hbr = CreateSolidBrush(col);
  374.     FillRect(hdc, &rc, hbr);
  375.     DeleteObject(hbr);
  376.     if(hbmpMenuLeft)
  377.     {
  378.         int i, j;
  379.         GetObject(hbmpMenuLeft, sizeof(BITMAP), &bmp);
  380.         // ビットマップ描画
  381.         for(i = 0; ; i++)
  382.         {
  383.             int y, ysrc, h, x, w;
  384.             for(j = 0; ; j++)
  385.             {
  386.                 y = hClient - ((i + 1) * bmp.bmHeight);
  387.                 ysrc = 0;
  388.                 h = bmp.bmHeight;
  389.                 if(y < 0)
  390.                 {
  391.                     y = 0;
  392.                     ysrc = ((i + 1) * bmp.bmHeight) - hClient;
  393.                     h -= ysrc;
  394.                 }
  395.                 x = j * bmp.bmWidth; w = bmp.bmWidth;
  396.                 if(x + w > wClient)
  397.                 {
  398.                     w -= ((j + 1) * bmp.bmWidth) - wClient;
  399.                 }
  400.                 if(w > 0 && h > 0)
  401.                     BitBlt(hdc, rc.left + x, rc.top + y, w, h,
  402.                         hdcMemMenuLeft, 0, ysrc, SRCCOPY);
  403.                 if(!bTile || w < bmp.bmWidth) break;
  404.             }
  405.             if(!bTile || y == 0) break;
  406.         }
  407.     }
  408. }
  409.  
  410.