home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
DOS/V Power Report 2001 June
/
VPR0106A.BIN
/
OLS
/
TCL228
/
TCL228.lzh
/
DLLSRC.lzh
/
startbtn.c
< prev
next >
Wrap
C/C++ Source or Header
|
1999-09-18
|
15KB
|
561 lines
/*-------------------------------------------
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);
WNDPROC oldWndProcStart = NULL, oldWndProcTask = NULL;
HWND hwndStart = NULL, hwndTask = NULL, hwndTray = NULL;
HBITMAP hbmpstart = NULL, hbmpstartold = NULL;
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();
// "button"と"MSTaskSwWClass"のウィンドウハンドルを得る
hwndStart = hwndTask = NULL;
hwndTray = GetParent(hwndClock); // TrayNotifyWnd
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)
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 && !IsWindowVisible(hwnd))
{
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);
}
}
}