This is because you don't have a window, None
, and then the system will assign a default icon.
这是因为你没有一个窗口,没有,然后系统会分配一个默认图标。
You can install a hook using SetWindowsHookEx
and then alter MessageBox
icon. For example let's use StackOverflow icon.
您可以使用SetWindowsHookEx安装钩子,然后更改MessageBox图标。例如,让我们使用StackOverflow图标。
#-*- coding: utf-8 -*-
#!python
from ctypes import *
from ctypes.wintypes import *
#recommended
#from ctypes import windll, c_int, c_int64, c_long, WINFUNCTYPE, POINTER, cast, c_wchar, byref
#from ctypes.wintypes import HMODULE, LPCWSTR, HANDLE, HINSTANCE, UINT, HWND, WPARAM, LPARAM, HHOOK, DWORD, BOOL, RECT, POINT
from os import path
import platform
#################################################################
RelPath = lambda file : path.join(path.dirname(path.abspath(__file__)), file)
#################################################################
GetModuleHandle = windll.kernel32.GetModuleHandleW
GetModuleHandle.restype = HMODULE
GetModuleHandle.argtypes = [LPCWSTR]
#################################################################
IMAGE_ICON = 1
LR_LOADFROMFILE = 0x00000010
LR_CREATEDIBSECTION = 0x00002000
LoadImage = windll.user32.LoadImageW
LoadImage.restype = HANDLE
LoadImage.argtypes = [HINSTANCE, LPCWSTR, UINT, c_int, c_int, UINT]
#################################################################
LRESULT = c_int64 if platform.architecture()[0] == "64bit" else c_long
SendMessage = windll.user32.SendMessageW
SendMessage.restype = LRESULT
SendMessage.argtypes = [HWND, UINT, WPARAM, LPARAM]
#################################################################
MB_OK = 0x00000000L
MessageBox = windll.user32.MessageBoxW
MessageBox.restype = c_int
MessageBox.argtypes = [HWND, LPCWSTR, LPCWSTR, UINT]
#################################################################
WH_CBT = 5
HCBT_ACTIVATE = 5
HOOKPROC = WINFUNCTYPE(LRESULT, c_int, WPARAM, LPARAM)
SetWindowsHookEx = windll.user32.SetWindowsHookExW
SetWindowsHookEx.restype = HHOOK
SetWindowsHookEx.argtypes = [c_int, HOOKPROC, HINSTANCE, DWORD]
#################################################################
CallNextHookEx = windll.user32.CallNextHookEx
CallNextHookEx.restype = LRESULT
CallNextHookEx.argtypes = [HHOOK, c_int, WPARAM, LPARAM]
#################################################################
GetCurrentThreadId = windll.kernel32.GetCurrentThreadId
GetCurrentThreadId.restype = DWORD
GetCurrentThreadId.argtypes = None
#################################################################
UnhookWindowsHookEx = windll.user32.UnhookWindowsHookEx
UnhookWindowsHookEx.restype = BOOL
UnhookWindowsHookEx.argtypes = [HHOOK]
#################################################################
# code starts here
def MyMessageBox(hWnd, lpText, lpCaption, uType, lpIcon):
hHook = HHOOK(None)
#**********************************************************#
# center button code
def EnumChildProc(hwnd, lParam):
ClassName = (c_wchar * 7)()
if GetClassName(hwnd, ClassName, 7) > 0:
if ClassName.value.lower() == "button":
wrect = RECT()
GetClientRect(lParam, byref(wrect))
brect = RECT()
GetClientRect(hwnd, byref(brect))
bpoint = RECT()
MapWindowPoints(hwnd, lParam, cast(byref(bpoint), POINTER(POINT)), 2)
MoveWindow(hwnd,
((wrect.right - wrect.left) - (brect.right - brect.left)) // 2,
bpoint.top,
brect.right - brect.left,
brect.bottom - brect.top,
True)
return False
return True
WNDENUMPROC = WINFUNCTYPE(BOOL, HWND, LPARAM)
EnumChildWindows = windll.user32.EnumChildWindows
EnumChildWindows.restype = BOOL
EnumChildWindows.argtypes = [HWND, WNDENUMPROC, LPARAM]
GetClassName = windll.user32.GetClassNameW
GetClassName.restype = HWND
GetClassName.argtypes = [HWND, LPCWSTR, c_int]
GetClientRect = windll.user32.GetClientRect
GetClientRect.restype = BOOL
GetClientRect.argtypes = [HWND, POINTER(RECT)]
MoveWindow = windll.user32.MoveWindow
MoveWindow.restype = BOOL
MoveWindow.argtypes = [HWND, c_int, c_int, c_int, c_int, BOOL]
MapWindowPoints = windll.user32.MapWindowPoints
MapWindowPoints.restype = c_int
MapWindowPoints.argtypes = [HWND, HWND, POINTER(POINT), UINT]
#**********************************************************#
def AlterIcon(_hWnd, lpszIcon):
WM_SETICON = 0x0080
ICON_BIG = 1
hModel = GetModuleHandle(None)
hIcon = LoadImage(hModel,
RelPath(lpszIcon),
IMAGE_ICON,
0, 0,
LR_LOADFROMFILE | LR_CREATEDIBSECTION)
SendMessage(_hWnd, WM_SETICON, ICON_BIG, hIcon)
def CBTProc(nCode, wParam, lParam):
if nCode == HCBT_ACTIVATE:
_hWnd = cast(wParam, HWND)
AlterIcon(_hWnd, lpIcon)
#**********************************************************#
pEnumChildProc = WNDENUMPROC(EnumChildProc)
EnumChildWindows(_hWnd, pEnumChildProc, _hWnd.value)
#**********************************************************#
CallNextHookEx(hHook, nCode, wParam, lParam)
return 0
# WARNING: don't pass HOOKPROC(CBTProc) directly to SetWindowsHookEx
pCBTProc = HOOKPROC(CBTProc)
hHook = SetWindowsHookEx(WH_CBT, pCBTProc, None, GetCurrentThreadId())
MessageBox(hWnd, lpText, lpCaption, uType)
UnhookWindowsHookEx(hHook)
# example of usage
MyMessageBox(None, "Hello world!", "Title", MB_OK, "favicon.ico")
Most the code is just functions prototype. Now you can call MyMessageBox
as:
大部分代码只是函数的原型。现在您可以这样调用MyMessageBox:
MyMessageBox(None, "Hello world!", "Title", MB_OK, "favicon.ico")
result:
结果:
UPDATE: it will center the button now by enumerating through the message box window's chillers and looking for a button, then center it. I haven't test it much but it looks OK so far.
更新:它现在将通过枚举消息框窗口的冷却器并查找按钮来居中按钮,然后将其居中。我没怎么试过,但到目前为止它看起来还可以。
更多回答
thanks for the answer. I doubt, how to use this code as a function, so that many time it is callable with different text messages.
谢谢你的回答。我怀疑,如何使用这个代码作为一个函数,使许多时候它是可调用的不同的文本消息。
@winterfall OK, I modified the code and wrapped these functions inside a single MyMessageBox
function.
@winterfall好的,我修改了代码,并将这些函数包装在单个MyMessageBox函数中。
thanks a lot, I really appreciate your help. Can this ok button be moved to center. I added the screenshot of alert box where ok button comes at end. Can it moved to center
非常感谢,我真的很感谢你的帮助。这个OK按钮可以移到中间吗?我添加了警告框的屏幕截图,其中OK按钮位于末尾。它能移到中间吗?
@winterfall There is no direct way to do this (it depends on the system and the theme I guess). I modified the code so it centers the button, it works well on Windows 7 but I haven't test it on other versions.
@Winterfall没有直接的方法可以做到这一点(我想这取决于系统和主题)。我修改了代码,使按钮居中,它在Windows7上运行良好,但我还没有在其他版本上测试过它。
@winterfall Yes I use 32bit Windows 7.
@Winterfall是的,我使用的是32位Windows 7。
我是一名优秀的程序员,十分优秀!