I found a recipe on ActiveState's Cookbook that shows how to change colours of an application's menu, and immediately recalled that Mushclient has that world.GetFrame callback. So here's a function that will add some colour to the menu bar in Mushclient. This requires you to have the ctypes package installed (in addition to a working Python installation of course). Ctypes is a tiny extension that allows you to call native DLL's - both *nix and Windows - directly from Python without requiring any additional wrapping.
""" Borrowed from ASPN Cookbook recipe:
aspn.activestate.com/ASPN/Cookbook/Python/Recipe/440507
"""
import win32con
from ctypes import *
# Structure passed to CreateSolidBrush function
# Represents RGB
class COLORREF(Structure):
_fields_ = [
("byRed", c_byte),
("byGreen", c_byte),
("byBlue", c_byte)
]
# Menu structure used in calls to SetMenuInfo
class MENUINFO(Structure):
_fields_ = [
("cbSize", c_long),
("fMask", c_long),
("dwStyle", c_long),
('cyMax', c_long),
("hbrBack", c_long),
("dwContextHelpID", c_long),
("dwMenuData", c_long)
]
user32 = windll.user32
DrawMenuBar = user32.DrawMenuBar
GetMenu = user32.GetMenu
GetSubMenu = user32.GetSubMenu
GetSystemMenu = user32.GetSystemMenu
SetMenuInfo = user32.SetMenuInfo
GetMenuInfo = user32.GetMenuInfo
gdi32 = windll.gdi32
CreateSolidBrush = gdi32.CreateSolidBrush
def ChangeMenuBarColor():
"""
Changes the background color of the menubar and optionally gives
different colors to menu items
"""
col = COLORREF(255,255,255)
# Get the frame handle
hwnd = c_int(int(world.GetFrame))
# Instantiate MENUINFO
menuinfo = MENUINFO()
# Important to set the size
menuinfo.cbSize = sizeof(MENUINFO)
menuinfo.fMask = win32con.MIM_BACKGROUND
col = COLORREF(55, 150, 12)
menuinfo.hbrBack = CreateSolidBrush(col)
# Important! Pass *pointer* of the menuinfo instance to the win32 call
SetMenuInfo(GetMenu(hwnd), byref(menuinfo))
menuinfo.fMask = win32con.MIM_BACKGROUND | win32con.MIM_APPLYTOSUBMENUS
col = COLORREF(255, 255, 0)
menuinfo.hbrBack = CreateSolidBrush(col)
SetMenuInfo(GetSubMenu(GetMenu(hwnd), 0), byref(menuinfo))
menuinfo.fMask = win32con.MIM_BACKGROUND | win32con.MIM_APPLYTOSUBMENUS
col = COLORREF(128, 255, 128)
menuinfo.hbrBack = CreateSolidBrush(col)
SetMenuInfo(GetSubMenu(GetMenu(hwnd), 1), byref(menuinfo))
menuinfo.fMask = win32con.MIM_BACKGROUND | win32con.MIM_APPLYTOSUBMENUS
menuinfo.hbrBack = CreateSolidBrush(col)
SetMenuInfo(GetSubMenu(GetMenu(hwnd), 2), byref(menuinfo))
menuinfo.fMask = win32con.MIM_BACKGROUND | win32con.MIM_APPLYTOSUBMENUS
menuinfo.hbrBack = CreateSolidBrush(col)
SetMenuInfo(GetSubMenu(GetMenu(hwnd), 3), byref(menuinfo))
menuinfo.fMask = win32con.MIM_BACKGROUND | win32con.MIM_APPLYTOSUBMENUS
menuinfo.hbrBack = CreateSolidBrush(col)
SetMenuInfo(GetSubMenu(GetMenu(hwnd), 4), byref(menuinfo))
menuinfo.fMask = win32con.MIM_BACKGROUND | win32con.MIM_APPLYTOSUBMENUS
menuinfo.hbrBack = CreateSolidBrush(col)
SetMenuInfo(GetSubMenu(GetMenu(hwnd), 5), byref(menuinfo))
menuinfo.fMask = win32con.MIM_BACKGROUND | win32con.MIM_APPLYTOSUBMENUS
menuinfo.hbrBack = CreateSolidBrush(col)
SetMenuInfo(GetSubMenu(GetMenu(hwnd), 6), byref(menuinfo))
menuinfo.fMask = win32con.MIM_BACKGROUND | win32con.MIM_APPLYTOSUBMENUS
menuinfo.hbrBack = CreateSolidBrush(col)
SetMenuInfo(GetSubMenu(GetMenu(hwnd), 7), byref(menuinfo))
menuinfo.fMask = win32con.MIM_BACKGROUND | win32con.MIM_APPLYTOSUBMENUS
menuinfo.hbrBack = CreateSolidBrush(col)
SetMenuInfo(GetSubMenu(GetMenu(hwnd), 8), byref(menuinfo))
menuinfo.fMask = win32con.MIM_BACKGROUND | win32con.MIM_APPLYTOSUBMENUS
menuinfo.hbrBack = CreateSolidBrush(col)
SetMenuInfo(GetSubMenu(GetMenu(hwnd), 9), byref(menuinfo))
DrawMenuBar(hwnd)
As you can see, after getting the window handle from Mushclient, the function above makes direct calls to User32 and GDI32 Windows libraries to set the new colour values. Put the above in your world file and just enter:
/ChangeMenuBarColor()
in the input window (if you have inline scripting enabled and your script prefix is the default "/").
The functionality of ctypes isn't limited to changing menu colours only, of course. There's alot more one can do with Win API, but as I don't know it at all I can't think of any particularly cool ways to hack up Mushclient's interface. Ideas?
EDIT: I seem to have somehow broken and then fixed this back. |
댓글
댓글 쓰기