From 51fb06c44ba80d4a69fc319727d1a73af41fa085 Mon Sep 17 00:00:00 2001 From: hobbs Date: Fri, 20 Aug 2004 00:40:31 +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 | 99 +++++++++++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 146 insertions(+), 15 deletions(-) diff --git a/ChangeLog b/ChangeLog index 1186ca8..ce2bbf5 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-18 Donal K. Fellows * generic/tkPanedWindow.c (optionSpecs): Add missing GEOMETRY flag diff --git a/win/tkWinDialog.c b/win/tkWinDialog.c index 2b18d45..af512ad 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.30.2.2 2004/02/13 01:26:41 hobbs Exp $ + * RCS: @(#) $Id: tkWinDialog.c,v 1.30.2.3 2004/08/20 00:40:32 hobbs Exp $ * */ @@ -62,6 +62,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; @@ -172,6 +175,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); /* @@ -2487,6 +2491,8 @@ Tk_MessageBoxObjCmd(clientData, interp, objc, objv) MSG_DEFAULT, MSG_ICON, MSG_MESSAGE, MSG_PARENT, MSG_TITLE, MSG_TYPE }; + ThreadSpecificData *tsdPtr = (ThreadSpecificData *) + Tcl_GetThreadData(&dataKey, sizeof(ThreadSpecificData)); tkwin = (Tk_Window) clientData; @@ -2594,12 +2600,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); /* @@ -2616,6 +2632,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 cfcc7c0..6f369f4 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.14.2.1 2004/05/03 22:40:58 hobbs Exp $ + * RCS: @(#) $Id: tkWinInt.h,v 1.14.2.2 2004/08/20 00:40:32 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 d4fdec9..7489132 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.54.2.1 2004/05/15 04:07:15 chengyemao Exp $ + * RCS: @(#) $Id: tkWinWm.c,v 1.54.2.2 2004/08/20 00:40:32 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; @@ -3373,6 +3446,7 @@ WmIconbitmapCmd(tkwin, winPtr, interp, objc, objv) /* If true, then set for all windows. */ int isDefault = 0; char *string; + TkWindow *useWinPtr = winPtr; /* window to apply to (NULL if -default) */ if ((objc < 3) || (objc > 5)) { Tcl_WrongNumArgs(interp, 2, objv, "window ?-default? ?image?"); @@ -3386,7 +3460,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) { @@ -3404,8 +3478,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 { @@ -3434,8 +3507,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; @@ -3457,8 +3530,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