让 win32 api 颜色选择器总是在最前面?
Make win32 api color chooser always on top?
我将按照此 在 tkinter 中包含一个颜色选择器,它会记住上次选择的颜色和自定义颜色。它按预期工作,但颜色选择器 window 始终创建在左上角。我想选择颜色选择器的初始位置,并将其设置为始终在最前面。有什么方法可以实现吗?
这是我目前的情况:
import ctypes
import ctypes.wintypes as wtypes
"""
thanks!
"""
class CHOOSECOLOR(ctypes.Structure):
""" " a class to represent CWPRETSTRUCT structure
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646830(v=vs.85).aspx"""
_fields_ = [
("lStructSize", wtypes.DWORD),
("hwndOwner", wtypes.HWND),
("hInstance", wtypes.HWND),
("rgbResult", wtypes.COLORREF),
("lpCustColors", ctypes.POINTER(wtypes.COLORREF)),
("Flags", wtypes.DWORD),
("lCustData", wtypes.LPARAM),
("lpfnHook", wtypes.LPARAM),
("lpTemplateName", ctypes.c_char_p),
]
class ColorChooser:
"""a class to represent Color dialog box
https://msdn.microsoft.com/en-gb/library/windows/desktop/ms646912(v=vs.85).aspx"""
CC_SOLIDCOLOR = 0x80
CC_FULLOPEN = 0x02
CC_RGBINIT = 0x01
WS_EX_TOPMOST = 0x08
custom_color_array = ctypes.c_uint32 * 16
color_chooser = ctypes.windll.Comdlg32.ChooseColorW
def to_custom_color_array(self, custom_colors):
custom_int_colors = self.custom_color_array()
for i in range(16):
custom_int_colors[i] = (
rgb_to_int(*custom_colors[i])
if i < len(custom_colors)
else rgb_to_int(*(255, 255, 255))
)
return custom_int_colors
def askcolor(self, initialColor, custom_colors):
struct = CHOOSECOLOR()
ctypes.memset(ctypes.byref(struct), 0, ctypes.sizeof(struct))
struct.lStructSize = ctypes.sizeof(struct)
struct.Flags = self.CC_SOLIDCOLOR | self.CC_FULLOPEN | self.CC_RGBINIT
struct.lpCustColors = self.to_custom_color_array(custom_colors)
struct.rgbResult = rgb_to_int(*initialColor)
if self.color_chooser(ctypes.byref(struct)):
result = int_to_rgb(struct.rgbResult)
else:
result = None
return result, struct.lpCustColors
def rgb_to_int(red, green, blue):
return red + (green << 8) + (blue << 16)
def int_to_rgb(int_color):
red = int_color & 255
green = (int_color >> 8) & 255
blue = (int_color >> 16) & 255
return red, green, blue
可以在WM_INITDIALOG
时使用lpfnHook
to control the generation of the dialog box, and then call SetWindowPos
调整生成对话框的位置
一些 C++ 代码:
UINT_PTR CALLBACK Lpcchookproc(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
if (message == WM_INITDIALOG)
{
SetWindowPos(hWnd, HWND_TOPMOST, 400, 400, 0, 0, SWP_NOSIZE);
}
return 0;
}
int main()
{
CHOOSECOLOR cc; // common dialog box structure
static COLORREF acrCustClr[16]; // array of custom colors
HBRUSH hbrush; // brush handle
static DWORD rgbCurrent; // initial color selection
// Initialize CHOOSECOLOR
ZeroMemory(&cc, sizeof(cc));
cc.lStructSize = sizeof(cc);
cc.lpCustColors = (LPDWORD)acrCustClr;
cc.Flags = CC_FULLOPEN | CC_RGBINIT | CC_ENABLEHOOK;
cc.lpfnHook = Lpcchookproc;
ChooseColor(&cc) == TRUE;
return 0;
}
感谢所有回复的人,这是我最终使用的。
import ctypes
import ctypes.wintypes as wtypes
"""
a color chooser for tkinter with initial color, and custom color settings.
"""
class CHOOSECOLOR(ctypes.Structure):
""" " a class to represent CWPRETSTRUCT structure
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646830(v=vs.85).aspx"""
_fields_ = [
("lStructSize", wtypes.DWORD),
("hwndOwner", wtypes.HWND),
("hInstance", wtypes.HWND),
("rgbResult", wtypes.COLORREF),
("lpCustColors", ctypes.POINTER(wtypes.COLORREF)),
("Flags", wtypes.DWORD),
("lCustData", wtypes.LPARAM),
("lpfnHook", wtypes.LPARAM),
("lpTemplateName", ctypes.c_char_p),
]
class ColorChooser:
"""a class to represent Color dialog box
https://msdn.microsoft.com/en-gb/library/windows/desktop/ms646912(v=vs.85).aspx"""
CC_SOLIDCOLOR = 0x80
CC_FULLOPEN = 0x02
CC_RGBINIT = 0x01
WS_EX_TOPMOST = 0x08
custom_color_array = ctypes.c_uint32 * 16
color_chooser = ctypes.windll.Comdlg32.ChooseColorW
def to_custom_color_array(self, custom_colors):
custom_int_colors = self.custom_color_array()
for i in range(16):
custom_int_colors[i] = (
rgb_to_int(*custom_colors[i])
if i < len(custom_colors)
else rgb_to_int(*(255, 255, 255))
)
return custom_int_colors
def askcolor(self, hostId, initialColor, custom_colors):
#hostId is .winfo_id() of parent window, colors are hex rgb string, and
#custom_colors accepts up to 16 hex strings.
struct = CHOOSECOLOR()
ctypes.memset(ctypes.byref(struct), 0, ctypes.sizeof(struct))
struct.lStructSize = ctypes.sizeof(struct)
struct.Flags = self.CC_SOLIDCOLOR | self.CC_FULLOPEN | self.CC_RGBINIT
struct.lpCustColors = self.to_custom_color_array(custom_colors)
struct.rgbResult = rgb_to_int(*initialColor)
struct.hwndOwner = hostId
if self.color_chooser(ctypes.byref(struct)):
result = int_to_rgb(struct.rgbResult)
else:
result = None
return result, [int_to_rgb(struct.lpCustColors[i]) for i in range(16)]
def rgb_to_int(red, green, blue):
return red + (green << 8) + (blue << 16)
def int_to_rgb(int_color):
red = int_color & 255
green = (int_color >> 8) & 255
blue = (int_color >> 16) & 255
return red, green, blue
我将按照此
这是我目前的情况:
import ctypes
import ctypes.wintypes as wtypes
"""
thanks!
"""
class CHOOSECOLOR(ctypes.Structure):
""" " a class to represent CWPRETSTRUCT structure
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646830(v=vs.85).aspx"""
_fields_ = [
("lStructSize", wtypes.DWORD),
("hwndOwner", wtypes.HWND),
("hInstance", wtypes.HWND),
("rgbResult", wtypes.COLORREF),
("lpCustColors", ctypes.POINTER(wtypes.COLORREF)),
("Flags", wtypes.DWORD),
("lCustData", wtypes.LPARAM),
("lpfnHook", wtypes.LPARAM),
("lpTemplateName", ctypes.c_char_p),
]
class ColorChooser:
"""a class to represent Color dialog box
https://msdn.microsoft.com/en-gb/library/windows/desktop/ms646912(v=vs.85).aspx"""
CC_SOLIDCOLOR = 0x80
CC_FULLOPEN = 0x02
CC_RGBINIT = 0x01
WS_EX_TOPMOST = 0x08
custom_color_array = ctypes.c_uint32 * 16
color_chooser = ctypes.windll.Comdlg32.ChooseColorW
def to_custom_color_array(self, custom_colors):
custom_int_colors = self.custom_color_array()
for i in range(16):
custom_int_colors[i] = (
rgb_to_int(*custom_colors[i])
if i < len(custom_colors)
else rgb_to_int(*(255, 255, 255))
)
return custom_int_colors
def askcolor(self, initialColor, custom_colors):
struct = CHOOSECOLOR()
ctypes.memset(ctypes.byref(struct), 0, ctypes.sizeof(struct))
struct.lStructSize = ctypes.sizeof(struct)
struct.Flags = self.CC_SOLIDCOLOR | self.CC_FULLOPEN | self.CC_RGBINIT
struct.lpCustColors = self.to_custom_color_array(custom_colors)
struct.rgbResult = rgb_to_int(*initialColor)
if self.color_chooser(ctypes.byref(struct)):
result = int_to_rgb(struct.rgbResult)
else:
result = None
return result, struct.lpCustColors
def rgb_to_int(red, green, blue):
return red + (green << 8) + (blue << 16)
def int_to_rgb(int_color):
red = int_color & 255
green = (int_color >> 8) & 255
blue = (int_color >> 16) & 255
return red, green, blue
可以在WM_INITDIALOG
时使用lpfnHook
to control the generation of the dialog box, and then call SetWindowPos
调整生成对话框的位置
一些 C++ 代码:
UINT_PTR CALLBACK Lpcchookproc(
HWND hWnd,
UINT message,
WPARAM wParam,
LPARAM lParam
)
{
if (message == WM_INITDIALOG)
{
SetWindowPos(hWnd, HWND_TOPMOST, 400, 400, 0, 0, SWP_NOSIZE);
}
return 0;
}
int main()
{
CHOOSECOLOR cc; // common dialog box structure
static COLORREF acrCustClr[16]; // array of custom colors
HBRUSH hbrush; // brush handle
static DWORD rgbCurrent; // initial color selection
// Initialize CHOOSECOLOR
ZeroMemory(&cc, sizeof(cc));
cc.lStructSize = sizeof(cc);
cc.lpCustColors = (LPDWORD)acrCustClr;
cc.Flags = CC_FULLOPEN | CC_RGBINIT | CC_ENABLEHOOK;
cc.lpfnHook = Lpcchookproc;
ChooseColor(&cc) == TRUE;
return 0;
}
感谢所有回复的人,这是我最终使用的。
import ctypes
import ctypes.wintypes as wtypes
"""
a color chooser for tkinter with initial color, and custom color settings.
"""
class CHOOSECOLOR(ctypes.Structure):
""" " a class to represent CWPRETSTRUCT structure
https://msdn.microsoft.com/en-us/library/windows/desktop/ms646830(v=vs.85).aspx"""
_fields_ = [
("lStructSize", wtypes.DWORD),
("hwndOwner", wtypes.HWND),
("hInstance", wtypes.HWND),
("rgbResult", wtypes.COLORREF),
("lpCustColors", ctypes.POINTER(wtypes.COLORREF)),
("Flags", wtypes.DWORD),
("lCustData", wtypes.LPARAM),
("lpfnHook", wtypes.LPARAM),
("lpTemplateName", ctypes.c_char_p),
]
class ColorChooser:
"""a class to represent Color dialog box
https://msdn.microsoft.com/en-gb/library/windows/desktop/ms646912(v=vs.85).aspx"""
CC_SOLIDCOLOR = 0x80
CC_FULLOPEN = 0x02
CC_RGBINIT = 0x01
WS_EX_TOPMOST = 0x08
custom_color_array = ctypes.c_uint32 * 16
color_chooser = ctypes.windll.Comdlg32.ChooseColorW
def to_custom_color_array(self, custom_colors):
custom_int_colors = self.custom_color_array()
for i in range(16):
custom_int_colors[i] = (
rgb_to_int(*custom_colors[i])
if i < len(custom_colors)
else rgb_to_int(*(255, 255, 255))
)
return custom_int_colors
def askcolor(self, hostId, initialColor, custom_colors):
#hostId is .winfo_id() of parent window, colors are hex rgb string, and
#custom_colors accepts up to 16 hex strings.
struct = CHOOSECOLOR()
ctypes.memset(ctypes.byref(struct), 0, ctypes.sizeof(struct))
struct.lStructSize = ctypes.sizeof(struct)
struct.Flags = self.CC_SOLIDCOLOR | self.CC_FULLOPEN | self.CC_RGBINIT
struct.lpCustColors = self.to_custom_color_array(custom_colors)
struct.rgbResult = rgb_to_int(*initialColor)
struct.hwndOwner = hostId
if self.color_chooser(ctypes.byref(struct)):
result = int_to_rgb(struct.rgbResult)
else:
result = None
return result, [int_to_rgb(struct.lpCustColors[i]) for i in range(16)]
def rgb_to_int(red, green, blue):
return red + (green << 8) + (blue << 16)
def int_to_rgb(int_color):
red = int_color & 255
green = (int_color >> 8) & 255
blue = (int_color >> 16) & 255
return red, green, blue