2014-01-08 78 views
0

我在Windows 7 64位機器上的Python 2.7中創建了一個消息框。它會在消息框中顯示錯誤消息給用戶。如何在Python中使用ctypes在消息框中包含圖像

import ctypes 

msgbox = ctypes.windll.user32.MessageBoxA 
ret = msgbox(None, 'message', 'title', 0) 
print ret 

這顯示所需的消息框。但在任務欄中,python的默認圖像出現這很煩人。所以,如何在任務欄中包含圖像。或者只是不要在任務欄中顯示python的默認圖像。

enter image description here

enter image description here

回答

3

這是因爲你沒有一個窗口,None,然後系統會分配一個默認的圖標。

您可以使用SetWindowsHookEx安裝掛鉤,然後更改MessageBox圖標。例如,讓我們使用StackOverflow icon

#-*- coding: utf-8 -*- 
#!python 

from ctypes import * 
from ctypes.wintypes import * 
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") 

大部分代碼只是函數原型。現在,您可以撥打MyMessageBox爲:

MyMessageBox(None, "Hello world!", "Title", MB_OK, "favicon.ico") 

結果:

enter image description here

UPDATE:它會通過消息框窗口的冷水機組枚舉和尋找一個按鈕,那麼現在中間的按鈕居中。我沒有太多的測試,但目前看起來沒問題。

+0

感謝您的回答。我懷疑,如何將這段代碼作爲一個函數使用,以便很多時候可以用不同的文本消息來調用它。 – imp

+0

@winterfall好的,我修改了代碼並將這些函數封裝在一個「MyMessageBox」函數中。 – 2014-01-17 08:36:09

+0

非常感謝,我非常感謝你的幫助。這個確定按鈕可以移動到中心位置嗎?我添加了警告框的屏幕截圖,其中ok按鈕在結尾處顯示。它可以移動到中心 – imp

相關問題