minigui/ncs控件集中的Spinbox控件存在一个问题,如下图,即使设置了字体,在运行时也不会应用指定的字体。

通过查看libmgncs-1.2.0的源码,找到了原因,Spinbox控件中用于显示数字的子控件是SLEdit,
以下是mspinbox.c代码片段,createBody用于创建子控件,可以看到editor为一个SLEdit对象
static mObject* mSpinBox_createBody(mSpinBox *self)
{
mObject *body;
DWORD dwStyle = GetWindowStyle(self->hwnd);
NCS_EVENT_HANDLER editor_handlers[] = {
{MSG_CHAR, editor_onChar},
{MSG_SETPIECE_PROPERTY, editor_onSetPieceProperty},
{NCS_NOTIFY_CODE(NCSN_EDIT_CHANGE), editor_onChanged},
{0, NULL}
};
//create a editor
mWidget * editor = ncsCreateWindow(NCSCTRL_SLEDIT, "",
spinbox_style_to_editor_style(dwStyle),
WS_EX_NONE,
100,
0, 0, 0, 0,
self->hwnd,
NULL,
NULL, //rdr_info
editor_handlers, //handlers,
(DWORD)self);
body = create_pieces(self, editor, dwStyle);
return body;
}
SLEdit本身是可以正常响应MSG_FONTCHANGED消息的,但是Spinbox作为容器控件并没有处理MSG_FONTCHANGED消息。所以SLEdit作为子控件根本收不到MSG_FONTCHANGED消息的,也就无法改变字体,只能使用默认的系统字体。
以下是mSpinBox.c的消息处理函数,可以看出,mSpinBox只处理了MSG_SETFOCUS,MSG_KILLFOCUS消息,就把控制权交给了父类(mSpinner)的消息处理函数。
static LRESULT mSpinBox_wndProc (mSpinBox* self, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message) {
case MSG_SETFOCUS:
{
if ((GetWindowStyle(self->hwnd) & NCSS_SPNBOX_AUTOFOCUS))
SetFocusChild (GetDlgItem(self->hwnd, 100));
break;
}
case MSG_KILLFOCUS:
{
SendDlgItemMessage (self->hwnd, 100, MSG_KILLFOCUS, 0, 0);
break;
}
default:
break;
}
return Class(mSpinner).wndProc((mSpinner*)self, message, wParam, lParam);
}
知道原因就有了解决办法
解决方案1
修改libmgncs-1.2.0的源码,修改上面的mSpinBox_wndProc函数,增加对MSG_FONTCHANGED消息的处理:
// 判断logfont是否为系统字体
static inline BOOL is_system_font(PLOGFONT logfont)
{
if(logfont){
for(int font_id = 0; font_id < NR_SYSLOGFONTS; ++font_id)
{
if(logfont == g_SysLogFont[font_id])
{
return TRUE;
}
}
}
return FALSE;
}
static LRESULT mSpinBox_wndProc (mSpinBox* self, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message) {
case MSG_SETFOCUS:
{
if ((GetWindowStyle(self->hwnd) & NCSS_SPNBOX_AUTOFOCUS))
SetFocusChild (GetDlgItem(self->hwnd, 100));
break;
}
case MSG_KILLFOCUS:
{
SendDlgItemMessage (self->hwnd, 100, MSG_KILLFOCUS, 0, 0);
break;
}
case MSG_FONTCHANGED:
{
// 为SLEdit控件创建字体
PLOGFONT self_font = GetWindowFont(self->hwnd);
// 如果是系统字体直接使用否则要创建一个副本
PLOGFONT editor_font = is_system_font(self_font)
? self_font
: CreateLogFontIndirect(self_font);
// 设置SLEdit字体,100为SLEdit控件的ID
PLOGFONT of = SetWindowFont (GetDlgItem(self->hwnd, 100), editor_font);
// 如果原字体不是系统字体,则销毁原字体,不能销毁系统字体
if(!is_system_font(of)){
DestroyLogFont(of);
}
return FALSE;
}
default:
break;
}
return Class(mSpinner).wndProc((mSpinner*)self, message, wParam, lParam);
}
解决方案2
修改自己的UI界面代码,在mSpinBox收到MSG_FONTCHANGED消息时设置SLEdit控件字体
代码与方案1相同,只是放在了了应用程序的onFontChanged中
static inline BOOL is_system_font(PLOGFONT logfont)
{
if(logfont){
for(int font_id = 0; font_id < NR_SYSLOGFONTS; ++font_id)
{
if(logfont == g_SysLogFont[font_id])
{
return TRUE;
}
}
}
return FALSE;
}
//$func @2628714496 onFontChanged -- Need by merge, don't modify
static void Spinbox1_onFontChanged (mWidget* self, UINT message)
{
PLOGFONT self_font = GetWindowFont(self->hwnd);
// 如果是系统字体直接使用否则要创建一个副本
PLOGFONT editor_font = is_system_font(self_font)
? self_font
: CreateLogFontIndirect(self_font);
mWidget* editor = ncsGetChildObj(self->hwnd,100);
PLOGFONT of = SetWindowFont(editor->hwnd,editor_font);
// PLOGFONT of = SetWindowFont (GetDlgItem(self->hwnd, 100), editor_font);
if(!is_system_font(of)){
DestroyLogFont(of);
}
}
//$handle @2628714496 -- Need by merge, don't modify
static NCS_EVENT_HANDLER Spinbox1_handlers [] = {
{MSG_FONTCHANGED,Spinbox1_onFontChanged},
//$user -- TODO add your handlers here
{-1,NULL}
};
执行结果:


文章指出Minigui/ncs控件集中的Spinbox控件无法应用指定字体的问题,并提供了两种解决方案:一是修改libmgncs-1.2.0源码处理MSG_FONTCHANGED消息;二是更改应用程序UI代码。
6066

被折叠的 条评论
为什么被折叠?



