summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog6
-rw-r--r--win/tkWinDialog.c49
-rw-r--r--win/tkWinInt.h7
-rw-r--r--win/tkWinWm.c99
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 <jeffh@ActiveState.com>
+
+ * 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 <donal.k.fellows@man.ac.uk>
* 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;