From 011a329f056b76453c8af9b2e9f89e1bfcc18824 Mon Sep 17 00:00:00 2001 From: hobbs Date: Fri, 20 Aug 2004 00:58:52 +0000 Subject: * win/tkWinDialog.c (Tk_MessageBoxObjCmd): Inherit the icon from * win/tkWinInt.h: the -parent window for * win/tkWinWm.c (TkWinGetIcon): the MessageBox. --- ChangeLog | 6 ++++ win/tkWinDialog.c | 49 +++++++++++++++++++++++++- win/tkWinInt.h | 7 +++- win/tkWinWm.c | 101 ++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 146 insertions(+), 17 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0ec1f8d..49c6b46 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2004-08-19 Jeff Hobbs + + * win/tkWinDialog.c (Tk_MessageBoxObjCmd): Inherit the icon from + * win/tkWinInt.h: the -parent window for + * win/tkWinWm.c (TkWinGetIcon): the MessageBox. + 2004-08-19 Joe English * unix/tkUnixWm.c: Cast argument 7 of XChangeProperty to diff --git a/win/tkWinDialog.c b/win/tkWinDialog.c index 61799dc..4a18942 100644 --- a/win/tkWinDialog.c +++ b/win/tkWinDialog.c @@ -8,7 +8,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinDialog.c,v 1.35 2004/05/24 21:23:23 dkf Exp $ + * RCS: @(#) $Id: tkWinDialog.c,v 1.36 2004/08/20 00:58:52 hobbs Exp $ * */ @@ -68,6 +68,9 @@ typedef struct ThreadSpecificData { UINT WM_LBSELCHANGED; /* Holds a registered windows event used for * communicating between the Directory * Chooser dialog and its hook proc. */ + HHOOK hMsgBoxHook; /* Hook proc for tk_messageBox and the */ + HICON hSmallIcon; /* icons used by a parent to be used in */ + HICON hBigIcon; /* the message box */ } ThreadSpecificData; static Tcl_ThreadDataKey dataKey; @@ -178,6 +181,7 @@ static UINT APIENTRY OFNHookProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam); static UINT APIENTRY OFNHookProcW(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam); +static LRESULT CALLBACK MsgBoxCBTProc(int nCode, WPARAM wParam, LPARAM lParam); static void SetTkDialog(ClientData clientData); /* @@ -2540,6 +2544,8 @@ Tk_MessageBoxObjCmd(clientData, interp, objc, objv) MSG_DEFAULT, MSG_DETAIL, MSG_ICON, MSG_MESSAGE, MSG_PARENT, MSG_TITLE, MSG_TYPE }; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); tkwin = (Tk_Window) clientData; @@ -2668,12 +2674,22 @@ Tk_MessageBoxObjCmd(clientData, interp, objc, objv) Tcl_UtfToExternalDString(unicodeEncoding, title, -1, &titleString); oldMode = Tcl_SetServiceMode(TCL_SERVICE_ALL); + /* * MessageBoxW exists for all platforms. Use it to allow unicode * error message to be displayed correctly where possible by the OS. + * + * In order to have the parent window icon reflected in a MessageBox, + * we have to create a hook that will trigger when the MessageBox is + * being created. */ + tsdPtr->hSmallIcon = TkWinGetIcon(parent, ICON_SMALL); + tsdPtr->hBigIcon = TkWinGetIcon(parent, ICON_BIG); + tsdPtr->hMsgBoxHook = SetWindowsHookEx(WH_CBT, MsgBoxCBTProc, NULL, + GetCurrentThreadId()); winCode = MessageBoxW(hWnd, (WCHAR *) Tcl_DStringValue(&messageString), (WCHAR *) Tcl_DStringValue(&titleString), flags); + UnhookWindowsHookEx(tsdPtr->hMsgBoxHook); (void) Tcl_SetServiceMode(oldMode); /* @@ -2690,6 +2706,37 @@ Tk_MessageBoxObjCmd(clientData, interp, objc, objv) return TCL_OK; } +static LRESULT CALLBACK +MsgBoxCBTProc(int nCode, WPARAM wParam, LPARAM lParam) +{ + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (nCode == HCBT_CREATEWND) { + /* + * Window owned by our task is being created. Since the hook is + * installed just before the MessageBox call and removed after the + * MessageBox call, the window being created is either the message + * box or one of its controls. Check that the class is WC_DIALOG + * to ensure that it's the one we want. + */ + LPCBT_CREATEWND lpcbtcreate = (LPCBT_CREATEWND)lParam; + + if (WC_DIALOG == lpcbtcreate->lpcs->lpszClass) { + HWND hwnd = (HWND) wParam; + SendMessage(hwnd, WM_SETICON, ICON_SMALL, + (LPARAM) tsdPtr->hSmallIcon); + SendMessage(hwnd, WM_SETICON, ICON_BIG, + (LPARAM) tsdPtr->hBigIcon); + } + } + + /* + * Call the next hook proc, if there is one + */ + return CallNextHookEx(tsdPtr->hMsgBoxHook, nCode, wParam, lParam); +} + static void SetTkDialog(ClientData clientData) { diff --git a/win/tkWinInt.h b/win/tkWinInt.h index 17e8d14..ba8ad84 100644 --- a/win/tkWinInt.h +++ b/win/tkWinInt.h @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinInt.h,v 1.15 2004/05/03 22:40:30 hobbs Exp $ + * RCS: @(#) $Id: tkWinInt.h,v 1.16 2004/08/20 00:58:52 hobbs Exp $ */ #ifndef _TKWININT @@ -166,6 +166,11 @@ EXTERN LRESULT CALLBACK TkWinChildProc _ANSI_ARGS_((HWND hwnd, UINT message, EXTERN void TkWinUpdatingClipboard(int mode); /* + * Used by tkWinDialog.c to associate the right icon with tk_messageBox + */ +EXTERN HICON TkWinGetIcon(Tk_Window tkw, DWORD iconsize); + +/* * The following structure keeps track of whether we are using the * multi-byte or the wide-character interfaces to the operating system. * System calls should be made through the following function table. diff --git a/win/tkWinWm.c b/win/tkWinWm.c index b7240a7..4fff379 100644 --- a/win/tkWinWm.c +++ b/win/tkWinWm.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tkWinWm.c,v 1.63 2004/06/16 20:03:20 jenglish Exp $ + * RCS: @(#) $Id: tkWinWm.c,v 1.64 2004/08/20 00:58:52 hobbs Exp $ */ #include "tkWinInt.h" @@ -798,7 +798,8 @@ ReadICOHeader( Tcl_Channel channel ) *---------------------------------------------------------------------- */ static int -InitWindowClass(WinIconPtr titlebaricon) { +InitWindowClass(WinIconPtr titlebaricon) +{ ThreadSpecificData *tsdPtr = (ThreadSpecificData *) Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); @@ -1064,6 +1065,74 @@ WinSetIcon(interp, titlebaricon, tkw) /* *---------------------------------------------------------------------- * + * TkWinGetIcon -- + * + * Gets either the default toplevel titlebar icon, or the icon + * for a specific toplevel (ICON_SMALL or ICON_BIG). + * + * Results: + * A Windows HICON. + * + * Side effects: + * The given window will be forced into existence. + * + *---------------------------------------------------------------------- + */ +HICON +TkWinGetIcon(Tk_Window tkw, DWORD iconsize) +{ + TkWindow *winPtr; + WmInfo *wmPtr; + HICON icon; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); + + if (tsdPtr->iconPtr != NULL) { + /* + * return default toplevel icon + */ + return GetIcon(tsdPtr->iconPtr, iconsize); + } + + if (Tk_WindowId(tkw) == None) { + Tk_MakeWindowExist(tkw); + } + + winPtr = (TkWindow *)tkw; + if (!(Tk_IsTopLevel(tkw))) { + winPtr = GetTopLevel(Tk_GetHWND(Tk_WindowId(tkw))); + } + /* We must get the window's wrapper, not the window itself */ + wmPtr = winPtr->wmInfoPtr; + + if (wmPtr->iconPtr != NULL) { + /* + * return window toplevel icon + */ + return GetIcon(wmPtr->iconPtr, iconsize); + } + + /* + * Find the icon otherwise associated with the toplevel, or + * finally with the window class. + */ + icon = (HICON) SendMessage(wmPtr->wrapper, WM_GETICON, iconsize, + (LPARAM) NULL); + if (icon == (HICON) NULL) { +#ifdef _WIN64 + icon = (HICON) GetClassLongPtr(wmPtr->wrapper, + (iconsize == ICON_BIG) ? GCLP_HICON : GCLP_ICONSM); +#else + icon = (HICON) GetClassLong(wmPtr->wrapper, + (iconsize == ICON_BIG) ? GCL_HICON : GCL_HICONSM); +#endif + } + return icon; +} + +/* + *---------------------------------------------------------------------- + * * ReadIconFromFile -- * * Read the contents of a file (usually .ico, .icr) and extract an @@ -1301,7 +1370,8 @@ DecrIconRefCount(WinIconPtr titlebaricon) { *---------------------------------------------------------------------- */ static void -FreeIconBlock(BlockOfIconImagesPtr lpIR) { +FreeIconBlock(BlockOfIconImagesPtr lpIR) +{ int i; /* Free all the bits */ @@ -1332,7 +1402,8 @@ FreeIconBlock(BlockOfIconImagesPtr lpIR) { *---------------------------------------------------------------------- */ static HICON -GetIcon(WinIconPtr titlebaricon, int icon_size) { +GetIcon(WinIconPtr titlebaricon, int icon_size) +{ BlockOfIconImagesPtr lpIR; if (titlebaricon == NULL) { @@ -1367,7 +1438,8 @@ GetIcon(WinIconPtr titlebaricon, int icon_size) { } static HCURSOR -TclWinReadCursorFromFile(Tcl_Interp* interp, Tcl_Obj* fileName) { +TclWinReadCursorFromFile(Tcl_Interp* interp, Tcl_Obj* fileName) +{ BlockOfIconImagesPtr lpIR; HICON res = NULL; @@ -1400,7 +1472,8 @@ TclWinReadCursorFromFile(Tcl_Interp* interp, Tcl_Obj* fileName) { *---------------------------------------------------------------------- */ static BlockOfIconImagesPtr -ReadIconOrCursorFromFile(Tcl_Interp* interp, Tcl_Obj* fileName, BOOL isIcon) { +ReadIconOrCursorFromFile(Tcl_Interp* interp, Tcl_Obj* fileName, BOOL isIcon) +{ BlockOfIconImagesPtr lpIR, lpNew; Tcl_Channel channel; int i; @@ -3380,8 +3453,7 @@ WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv) Tcl_Obj *CONST objv[]; /* Argument objects. */ { register WmInfo *wmPtr = winPtr->wmInfoPtr; - /* If true, then set for all windows. */ - int isDefault = 0; + TkWindow *useWinPtr = winPtr; /* window to apply to (NULL if -default) */ char *string; if ((objc < 3) || (objc > 5)) { @@ -3396,7 +3468,7 @@ WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv) (char *) NULL); return TCL_ERROR; } - isDefault = 1; + useWinPtr = NULL; } else if (objc == 3) { /* No arguments were given */ if (wmPtr->hints.flags & IconPixmapHint) { @@ -3414,8 +3486,7 @@ WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv) wmPtr->hints.icon_pixmap = None; } wmPtr->hints.flags &= ~IconPixmapHint; - if (WinSetIcon(interp, NULL, - (isDefault ? NULL : (Tk_Window) winPtr)) != TCL_OK) { + if (WinSetIcon(interp, NULL, (Tk_Window) useWinPtr) != TCL_OK) { return TCL_ERROR; } } else { @@ -3444,8 +3515,8 @@ WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv) * Try to set the icon for the window. If it is a '-default' * icon, we must pass in NULL */ - if (WinSetIcon(interp, titlebaricon, - (isDefault ? NULL : (Tk_Window) winPtr)) != TCL_OK) { + if (WinSetIcon(interp, titlebaricon, (Tk_Window) useWinPtr) + != TCL_OK) { /* We didn't use the titlebaricon after all */ DecrIconRefCount(titlebaricon); titlebaricon = NULL; @@ -3467,8 +3538,8 @@ WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv) wmPtr->hints.flags |= IconPixmapHint; titlebaricon = GetIconFromPixmap(Tk_Display(winPtr), pixmap); if (titlebaricon != NULL) { - if (WinSetIcon(interp, titlebaricon, - (isDefault ? NULL : (Tk_Window) winPtr)) != TCL_OK) { + if (WinSetIcon(interp, titlebaricon, (Tk_Window) useWinPtr) + != TCL_OK) { /* We didn't use the titlebaricon after all */ DecrIconRefCount(titlebaricon); titlebaricon = NULL; -- cgit v0.12