home *** CD-ROM | disk | FTP | other *** search
- /*-------------------------------------------
- startbtn.c
- customize start button
- Kazubon 1997-1999
- ---------------------------------------------*/
-
- #include "tcdll.h"
-
- extern HANDLE hmod;
-
- /*------------------------------------------------
- globals
- --------------------------------------------------*/
- LRESULT CALLBACK WndProcStart(HWND, UINT, WPARAM, LPARAM);
- LRESULT CALLBACK WndProcTask(HWND, UINT, WPARAM, LPARAM);
- HWND hwndStart = NULL;
- BOOL bStartMenuClock = FALSE;
-
- static WNDPROC oldWndProcStart = NULL, oldWndProcTask = NULL;
- static HWND hwndTask = NULL, hwndTray = NULL;
- static HBITMAP hbmpstart = NULL, hbmpstartold = NULL;
- static int wStart = -1, hStart = -1;
- static BOOL bCustStartButton = FALSE;
- static BOOL bHideStartButton = FALSE;
- static BOOL bStartButtonFlat = FALSE;
- static BOOL bCursorOnStartButton = FALSE;
-
- static void OnPaint(HWND hwnd, HDC hdc);
- static void SetStartButtonBmp(void);
- static void SetTaskWinPos(void);
-
- /*--------------------------------------------------
- initialize
- ----------------------------------------------------*/
- void SetStartButton(HWND hwndClock)
- {
- HANDLE hwnd;
- char classname[80];
-
- EndStartButton();
-
- bStartMenuClock = FALSE;
- if(GetMyRegLong(NULL, "StartButtonHide", FALSE))
- bStartMenuClock =
- GetMyRegLong(NULL, "StartMenuClock", FALSE);
-
- // "button"と"MSTaskSwWClass"のウィンドウハンドルを得る
- hwndStart = hwndTask = NULL;
- hwndTray = GetParent(hwndClock); // TrayNotifyWnd
- if(hwndTray == NULL)
- return;
- hwnd = GetParent(hwndTray); // Shell_TrayWnd
- if(hwnd == NULL)
- return;
-
- hwnd = GetWindow(hwnd, GW_CHILD);
- while(hwnd)
- {
- GetClassName(hwnd, classname, 80);
- if(lstrcmpi(classname, "Button") == 0)
- hwndStart = hwnd;
- else if(lstrcmpi(classname, "MSTaskSwWClass") == 0)
- hwndTask = hwnd;
- else if(lstrcmpi(classname, "ReBarWindow32") == 0)
- hwndTask = hwnd;
- hwnd = GetWindow(hwnd, GW_HWNDNEXT);
- }
- if(hwndStart == NULL || hwndTask == NULL)
- {
- hwndStart = hwndTask = NULL; return;
- }
-
- bCustStartButton = GetMyRegLong(NULL, "StartButton", FALSE);
- bHideStartButton = GetMyRegLong(NULL, "StartButtonHide", FALSE);
- bStartButtonFlat = GetMyRegLong(NULL, "StartButtonFlat", FALSE);
- if(!bCustStartButton && !bHideStartButton && !bStartButtonFlat) return;
-
- // サブクラス化
- oldWndProcStart = (WNDPROC)GetWindowLong(hwndStart, GWL_WNDPROC);
- SetWindowLong(hwndStart, GWL_WNDPROC, (LONG)WndProcStart);
- oldWndProcTask = (WNDPROC)GetWindowLong(hwndTask, GWL_WNDPROC);
- SetWindowLong(hwndTask, GWL_WNDPROC, (LONG)WndProcTask);
-
- if(bHideStartButton) // ボタンを隠す
- {
- RECT rc; POINT pt;
- ShowWindow(hwndStart, SW_HIDE);
- wStart = 0; hStart = 0;
- GetWindowRect(hwndTray, &rc);
- pt.x = rc.left; pt.y = rc.top;
- ScreenToClient(GetParent(hwndTray), &pt);
- SetWindowPos(hwndStart, NULL, pt.x, pt.y,
- rc.right - rc.left, rc.bottom - rc.top,
- SWP_NOZORDER|SWP_NOACTIVATE);
- }
- else if(bCustStartButton)
- {
- // ボタン用ビットマップの設定
- SetStartButtonBmp();
- }
- // MSTaskSwWClassの位置・サイズの設定
- if(bCustStartButton || bHideStartButton)
- SetTaskWinPos();
- }
-
- /*--------------------------------------------------
- reset start button
- ----------------------------------------------------*/
- void EndStartButton(void)
- {
- if(hwndStart && IsWindow(hwndStart))
- {
- if(hbmpstartold != NULL)
- {
- SendMessage(hwndStart, BM_SETIMAGE,
- 0, (LPARAM)hbmpstartold);
- hbmpstartold = NULL;
- }
- if(oldWndProcStart)
- SetWindowLong(hwndStart, GWL_WNDPROC, (LONG)oldWndProcStart);
- oldWndProcStart = NULL;
- SetWindowPos(hwndStart, NULL, 0, 0, 0, 0,
- SWP_NOSIZE|SWP_NOZORDER|SWP_NOACTIVATE);
- ShowWindow(hwndStart, SW_SHOW);
- }
- hwndStart = NULL;
-
- if(hbmpstart) DeleteObject(hbmpstart); hbmpstart = NULL;
-
- if(hwndTask && IsWindow(hwndTask) && oldWndProcTask)
- SetWindowLong(hwndTask, GWL_WNDPROC, (LONG)oldWndProcTask);
- oldWndProcTask = NULL; hwndStart = NULL;
-
- bCustStartButton = bHideStartButton = bStartButtonFlat = FALSE;
- }
-
- /*------------------------------------------------
- subclass procedure of start button
- --------------------------------------------------*/
- LRESULT CALLBACK WndProcStart(HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam)
- {
- switch(message)
- {
- case WM_SYSCOLORCHANGE: // システムの設定変更
- case WM_WININICHANGE:
- if(bCustStartButton && !bHideStartButton)
- PostMessage(hwnd, WM_USER+10, 0, 0L);
- return 0;
- case (WM_USER + 10): // 再初期化
- SetStartButtonBmp();
- return 0;
- case WM_WINDOWPOSCHANGING: // サイズを変更させない
- {
- LPWINDOWPOS pwp;
- if(!(bCustStartButton || bHideStartButton)) break;
- pwp = (LPWINDOWPOS)lParam;
- if(!(pwp->flags & SWP_NOSIZE))
- {
- if(wStart > 0) pwp->cx = wStart;
- if(hStart > 0) pwp->cy = hStart;
- }
- if(bHideStartButton)
- {
- RECT rc; POINT pt;
- GetWindowRect(hwndTray, &rc);
- pt.x = rc.left; pt.y = rc.top;
- ScreenToClient(GetParent(hwndTray), &pt);
- pwp->x = pt.x; pwp->y = pt.y;
- pwp->cx = rc.right - rc.left;
- pwp->cy = rc.bottom - rc.top;
- }
- break;
- }
- case WM_DESTROY:
- if(hbmpstartold)
- SendMessage(hwndStart, BM_SETIMAGE,
- 0, (LPARAM)hbmpstartold);
- hbmpstartold = NULL;
- if(hbmpstart) DeleteObject(hbmpstart); hbmpstart = NULL;
- break;
-
- // -------- for "flat start button" -----------
- case WM_PAINT:
- {
- HDC hdc;
- PAINTSTRUCT ps;
- if(!bStartButtonFlat) break;
- hdc = BeginPaint(hwnd, &ps);
- OnPaint(hwnd, hdc);
- EndPaint(hwnd, &ps);
- return 0;
- }
- case BM_SETSTATE:
- {
- LRESULT r;
- HDC hdc;
- if(!bStartButtonFlat) break;
- r = CallWindowProc(oldWndProcStart, hwnd, message, wParam, lParam);
- hdc = GetDC(hwnd);
- OnPaint(hwnd, hdc);
- ReleaseDC(hwnd, hdc);
- return 0;
- }
- case WM_SETFOCUS:
- if(!bStartButtonFlat) break;
- return 0;
- case WM_MOUSEMOVE:
- CheckCursorOnStartButton();
- break;
- }
- return CallWindowProc(oldWndProcStart, hwnd, message, wParam, lParam);
- }
-
- /*--------------------------------------------------
- subclass procedure of
- "MSTaskSwWClass"/"ReBarWindow32" class window
- ----------------------------------------------------*/
- LRESULT CALLBACK WndProcTask(HWND hwnd, UINT message,
- WPARAM wParam, LPARAM lParam)
- {
- switch(message)
- {
- case WM_WINDOWPOSCHANGING: // 位置・サイズの制限
- {
- LPWINDOWPOS pwp;
- RECT rcBar, rcTray;
-
- if(!(bCustStartButton || bHideStartButton)) break;
-
- pwp = (LPWINDOWPOS)lParam;
- // if((pwp->flags & SWP_NOMOVE) ||
- // wStart < 0 || hStart < 0) break;
-
- GetClientRect(GetParent(hwndStart), &rcBar); // タスクバー
- GetWindowRect(hwndTray, &rcTray); // TrayNotifyWnd
-
- // タスクバーが横置きのとき
- if(rcBar.right > rcBar.bottom)
- {
- pwp->x = 2 + wStart; // 右位置
- pwp->cx = rcTray.left - 2 - wStart - 2; // 横幅
- if(wStart > 0)
- {
- pwp->x += 2; pwp->cx -= 2;
- }
- }
- else // 縦置きのとき
- {
- if(rcTray.top < pwp->y)
- {
- pwp->cy = rcBar.bottom - 2 - hStart - 2; // 高さ
- }
- else
- {
- pwp->cy = rcTray.top - 2 - hStart - 2; // 高さ
- }
- pwp->y = 2 + hStart; // 上位置
- if(hStart > 0)
- {
- pwp->y += 1; pwp->cy -= 2;
- }
- }
- break;
- }
- }
- return CallWindowProc(oldWndProcTask, hwnd, message, wParam, lParam);
- }
-
- /*--------------------------------------------------
- スタートボタンのビットマップとサイズの設定
- ----------------------------------------------------*/
- void SetStartButtonBmp(void)
- {
- char s[1024], caption[80];
- HBITMAP hbmpicon, hbmpold;
- HICON hicon;
- HDC hdc, hdcMem;
- HFONT hfont;
- BITMAP bmp;
- int whbmp, hhbmp, cxicon, cyicon;
-
- if(hwndStart == NULL) return;
-
- hbmpicon = NULL; hicon = NULL;
- cxicon = GetSystemMetrics(SM_CXSMICON);
- cyicon = GetSystemMetrics(SM_CYSMICON);
-
- // ファイルからアイコン用ビットマップの読み込み
- if(GetMyRegStr(NULL, "StartButtonIcon", s, 1024, "") > 0)
- {
- char fname[MAX_PATH], head[2];
- HFILE hf;
-
- parse(fname, s, 0);
- hf = _lopen(fname, OF_READ);
- if(hf != HFILE_ERROR)
- {
- _lread(hf, head, 2);
- _lclose(hf);
- if(head[0] == 'B' && head[1] == 'M') //ビットマップの場合
- hbmpicon = ReadBitmap(hwndStart, fname, TRUE);
- else if(head[0] == 'M' && head[1] == 'Z') //実行ファイルの場合
- {
- char numstr[10], *p; int n;
- HICON hiconl;
- parse(numstr, s, 1);
- n = 0; p = numstr;
- while(*p)
- {
- if(*p < '0' || '9' < *p) break;
- n = n * 10 + *p++ - '0';
- }
- if(ExtractIconEx(fname, n, &hiconl, &hicon, 1) < 2)
- hicon = NULL;
- else DestroyIcon(hiconl);
- }
- else // アイコンの場合
- {
- hicon = (HICON)LoadImage(hmod, fname,
- IMAGE_ICON, cxicon, cyicon,
- LR_DEFAULTCOLOR|LR_LOADFROMFILE);
- }
- }
- }
-
- if(hbmpicon)
- {
- GetObject(hbmpicon, sizeof(BITMAP), (LPVOID)&bmp);
- cxicon = bmp.bmWidth; cyicon = bmp.bmHeight;
- }
-
- // キャプションの取得
- GetMyRegStr(NULL, "StartButtonCaption", caption, 80, "");
-
- hdc = GetDC(hwndStart);
-
- // ボタン用のフォント = タイトルバーのフォント + BOLD
- hfont = NULL;
- whbmp = cxicon; hhbmp = cyicon;
- if(caption[0])
- {
- NONCLIENTMETRICS ncm;
- SIZE sz;
- ncm.cbSize = sizeof(ncm);
- SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncm, 0);
- ncm.lfCaptionFont.lfWeight = FW_BOLD;
- hfont = CreateFontIndirect(&(ncm.lfCaptionFont));
- SelectObject(hdc, hfont);
-
- //キャプションの幅を得る
- GetTextExtentPoint32(hdc, caption, strlen(caption), &sz);
- whbmp = sz.cx;
- if(hbmpicon || hicon) whbmp += cxicon + 2;
- hhbmp = sz.cy;
- if((hbmpicon || hicon) && cyicon > sz.cy)
- hhbmp = cyicon;
- //if(hhbmp < 16) hhbmp = 16;
- }
-
- // ビットマップの作成
- hdcMem = CreateCompatibleDC(hdc);
- hbmpstart = CreateCompatibleBitmap(hdc, whbmp, hhbmp);
- SelectObject(hdcMem, hbmpstart);
-
- { // 背景色で塗りつぶし
- RECT rc; HBRUSH hbr;
- SetRect(&rc, 0, 0, whbmp, hhbmp);
- hbr = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
- FillRect(hdcMem, &rc, hbr);
- DeleteObject(hbr);
- }
-
- // ビットマップにアイコンの絵を描画
- if(hbmpicon)
- {
- HDC hdcicon;
- hdcicon = CreateCompatibleDC(hdc);
- SelectObject(hdcicon, hbmpicon);
- BitBlt(hdcMem, 0, (hhbmp - cyicon)/2,
- cxicon, cyicon, hdcicon, 0, 0, SRCCOPY);
- DeleteDC(hdcicon);
- DeleteObject(hbmpicon);
- }
- if(hicon)
- {
- DrawIconEx(hdcMem, 0, (hhbmp - cyicon)/2,
- hicon, cxicon, cyicon, 0, NULL, DI_NORMAL);
- DestroyIcon(hicon);
- }
-
- // ビットマップにキャプションを書く
- if(caption[0])
- {
- TEXTMETRIC tm;
- int x, y;
-
- GetTextMetrics(hdc, &tm);
- SelectObject(hdcMem, hfont);
- x = 0; if(hbmpicon || hicon) x = cxicon + 2;
- y = (hhbmp - tm.tmHeight) / 2;
- SetBkMode(hdcMem, TRANSPARENT);
- SetTextColor(hdcMem, GetSysColor(COLOR_BTNTEXT));
- TextOut(hdcMem, x, y, caption, strlen(caption));
- }
-
- DeleteDC(hdcMem);
- ReleaseDC(hwndStart, hdc);
- if(hfont) DeleteObject(hfont);
-
- // ボタンにビットマップを設定
- hbmpold = (HBITMAP)SendMessage(hwndStart,
- BM_SETIMAGE, 0, (LPARAM)hbmpstart);
- // 以前のビットマップを保存 / 破棄
- if(hbmpstartold == NULL) hbmpstartold = hbmpold;
- else DeleteObject(hbmpold);
-
- // ボタンのサイズの設定 上限:160x80
- wStart = whbmp + 8;
- if(wStart > 160) wStart = 160;
- hStart = GetSystemMetrics(SM_CYCAPTION) + 3;
- if(hhbmp + 6 > hStart) hStart = hhbmp + 6;
- if(hStart > 80) hStart = 80;
- SetWindowPos(hwndStart, NULL, 0, 0,
- wStart, hStart,
- SWP_NOMOVE|SWP_NOZORDER|SWP_NOACTIVATE);
- }
-
- /*--------------------------------------------------
- MSTaskSwWClassの位置・サイズの設定
- ----------------------------------------------------*/
- void SetTaskWinPos(void)
- {
- RECT rcBar, rcTask, rcTray;
- POINT pt;
- int x, y, w, h;
-
- GetClientRect(GetParent(hwndStart), &rcBar); // Shell_TrayWnd
- GetWindowRect(hwndTray, &rcTray); // TrayNotifyWnd
- GetWindowRect(hwndTask, &rcTask); // MSTaskSwWClass
-
- // MSTaskSwWClassの右上位置
- pt.x = rcTask.left; pt.y = rcTask.top;
- ScreenToClient(GetParent(hwndStart), &pt);
-
- x = pt.x; y = pt.y;
- w = rcTask.right - rcTask.left;
- h = rcTask.bottom - rcTask.top;
-
- // タスクバーが横置きのとき
- if(rcBar.right > rcBar.bottom)
- {
- x = 2 + wStart;
- w = rcTray.left - 2 - wStart - 2;
- if(wStart > 0)
- {
- x += 2; w -= 2;
- }
- }
- else // 縦置きのとき
- {
- y = 2 + hStart;
- h = rcTray.top - 2 - hStart - 2;
- if(hStart > 0)
- {
- y += 1; h -= 2;
- }
- }
- SetWindowPos(hwndTask, NULL, x, y, w, h,
- SWP_NOZORDER|SWP_NOACTIVATE);
- }
-
- /*--------------------------------------------------
- draw "flat start button"
- ----------------------------------------------------*/
- void OnPaint(HWND hwnd, HDC hdc)
- {
- HDC hdcMem1, hdcMem2;
- HBITMAP hbmp, hbmpTemp;
- HBRUSH hbr;
- BITMAP bmp;
- RECT rc;
- int x, y, w, h;
- BOOL bPushed;
-
- bPushed = (SendMessage(hwnd, BM_GETSTATE, 0, 0) & BST_PUSHED)?1:0;
-
- hdcMem1 = CreateCompatibleDC(hdc);
- hbmp = (HBITMAP)SendMessage(hwnd, BM_GETIMAGE, IMAGE_BITMAP, 0);
- SelectObject(hdcMem1, hbmp);
- GetObject(hbmp, sizeof(BITMAP), (LPVOID)&bmp);
- w = bmp.bmWidth; h = bmp.bmHeight;
-
- hdcMem2 = CreateCompatibleDC(hdc);
- GetClientRect(hwnd, &rc);
- hbmpTemp = CreateCompatibleBitmap(hdc, rc.right, rc.bottom);
- SelectObject(hdcMem2, hbmpTemp);
-
- hbr = CreateSolidBrush(GetSysColor(COLOR_3DFACE));
- FillRect(hdcMem2, &rc, hbr);
- DeleteObject(hbr);
-
- x = (rc.right - w)/2 + (!bCustStartButton ? 2:0) + (int)bPushed;
- y = (rc.bottom - h)/2 + (int)bPushed;
- BitBlt(hdcMem2, x, y, w, h, hdcMem1, 0, 0, SRCCOPY);
-
- if(bPushed || bCursorOnStartButton) // draw frame
- {
- HPEN hpen, hpenold;
- int color;
-
- color = GetSysColor(bPushed?COLOR_3DSHADOW:COLOR_3DHILIGHT);
- hpen = CreatePen(PS_SOLID, 1, color);
- hpenold = SelectObject(hdcMem2, hpen);
- MoveToEx(hdcMem2, 0, 0, NULL);
- LineTo(hdcMem2, rc.right, 0);
- MoveToEx(hdcMem2, 0, 0, NULL);
- LineTo(hdcMem2, 0, rc.bottom);
- SelectObject(hdcMem2, hpenold);
- DeleteObject(hpen);
-
- color = GetSysColor(bPushed?COLOR_3DHILIGHT:COLOR_3DSHADOW);
- hpen = CreatePen(PS_SOLID, 1, color);
- hpenold = SelectObject(hdcMem2, hpen);
- MoveToEx(hdcMem2, rc.right-1, 0, NULL);
- LineTo(hdcMem2, rc.right-1, rc.bottom);
- MoveToEx(hdcMem2, 0, rc.bottom-1, NULL);
- LineTo(hdcMem2, rc.right, rc.bottom-1);
- SelectObject(hdcMem2, hpenold);
- DeleteObject(hpen);
- }
-
- BitBlt(hdc, 0, 0,
- rc.right, rc.bottom, hdcMem2, 0, 0, SRCCOPY);
-
- DeleteDC(hdcMem1);
- DeleteDC(hdcMem2);
- DeleteObject(hbmpTemp);
- }
-
- /*--------------------------------------------------
- called when clock window receive WM_TIMER.
- check cursor position, and draw "flat start button"
- ----------------------------------------------------*/
- void CheckCursorOnStartButton(void)
- {
- POINT pt;
- RECT rc;
-
- if(hwndStart == NULL) return;
- if(!bStartButtonFlat) return;
-
- GetCursorPos(&pt);
- GetWindowRect(hwndStart, &rc);
- if(PtInRect(&rc, pt))
- {
- if(!bCursorOnStartButton)
- {
- bCursorOnStartButton = TRUE;
- InvalidateRect(hwndStart, NULL, FALSE);
- }
- }
- else
- {
- if(bCursorOnStartButton)
- {
- bCursorOnStartButton = FALSE;
- InvalidateRect(hwndStart, NULL, FALSE);
- }
- }
- }
-
-