月度归档:2021年08月

窗口行为与绘制行为的区分

1、窗口中的空间在鼠标移动时需要更改状态

2、窗口行为: 鼠标事件、窗口刷新、输出到屏幕

3、绘制行为: 控件状态、具体绘制

win32:

wndproc: 开发者实现, 默认的处理函数

rander: vui2lib

user:

1)mousemove/lbutton/rbutton 到 wndproc

2) 转换为event到vui2lib, vui2lib更改控件状态

3)wndproc 判断改变, 并刷新

4)event的后续处理, 如: 事件回调

如何在对话框中设置控件的焦点

在对话框中设置焦点时,只调用SetFocus是不够的.

在MSDN介绍DM_SETDEFID的文档中指出, 对默认ID的不当操作可能导致奇怪的情况, 例如在对护框中包含连个默认按钮. 幸运的是, 你很少改变对护框的默认按钮.

一个更大的问题是使用SetFocus函数来在对护框中设置焦点. 如果这么做, 那就是直接进入到窗口管理器, 而绕过了对话框管理器. 这就意味着将可能出现一些“不合理”的情况, 例如吧焦点放到一个按钮上, 而这个按钮不是默认按钮.

为了避免这个问题, 不要使用SetFocus来改变对话框上的焦点,而是使用WM_NEXTDLGCTL消息.

void SetDialogFocus(HWND HDlg, HWND hwndControl)
{
  SendMessage(Hdlg, WM_NEXTDLGCTRL, (WPARAM)hwndControl,  TRUE);
}

为什么SetFocus不会管理默认的ID

windows对话框管理器是建立在窗口管理器之上的. 由于SetFocus是窗口管理器中的函数. 因此, 它不知道接收焦点的窗口是否是在某个对话框内.如果只是检查父窗口的窗口类是不是对话框, 还是不够的. 同样, 在前面已经看到了, 在应用程序中可以使用IsDialogMessage函数在窗口中支持键盘导航(使用键盘控制窗口), 而这些窗口看你根本就不是对话框. 窗口管理器不能只是发送DM_GETDEFID消息到拥有焦点窗口的父窗口, 因为DM_GETDEFID在数值上等于WM_USER, 而WM_USER在窗口类内部定义的消息范围之内. 如果父窗口不是对话框, 那么当我们向窗口发送WM_USER消息时, 结果是不可预知的.

关于自己实现模态对话框时,禁止窗口和激活窗口的正确顺序

显示模态到取消模态,所有者窗口显示会“闪烁”的原因:

当销毁模态对话框时,这个对话框刚好是拥有前台焦点的窗口。现在,窗口管理器需要找到其它的窗口并把前台焦点交给这个窗口。窗口管理器会首先试着把前台焦点交给对话框的所有者窗口,但此时这个窗口却是“禁用”的,因此窗口管理器跳过所有者窗口,并继续查找其他没有被禁用的窗口。

因此,销毁模态对话框的正确顺序是:

1、重新激活所有者窗口

2、销毁模态对话框

关于Windows TextOut输出文字时的一些难看的“方块”

什么是绘制实心矩形最好的方式

老一辈的程序员可能会告诉你”ExtTextOut”,性能最优。

TextOut在输出文字时,为什么有些难看的方块?

IMLangFontLink2::GetStrCodePages方法将字符串分解成许多”块“(chunk),并且在每个块中的所有字符都可以用相同的字体来显示,此外还可以通过IMLangFontLink2::MapFont来创建字体。

#include <mlang.h>

HRESULT TextOutFL(HDC hdc, int x, int y, LPCWSTR psz, int cch)
{
  ...
  while (cch > 0) {
    DWORD dwActualCodePages;
    long cchActual;
    pfl->GetStrCodePages(psz, cch, 0, &dwActualCodePages, &cchActual);
    HFONT hfLinked;
    pfl->MapFont(hdc, dwActualCodePages, 0, &hfLinked);
    HFONT hfOrig = SelectFont(hdc, hfLinked);
    TextOut(hdc, ?, ?, psz, cchActual);
    SelectFont(hdc, hfOrig);
    pfl->ReleaseFont(hfLinked);
    psz += cchActual;
    cch -= cchActual;
  }
  ...
}

下一步,应该确定每次TextOut的位置

SetTextAlign(hdc, GetTextAlign(hdc) | TA_UPDATECP);
MoveToEx(hdc, x, y, NULL);

最后,在处理从右到左(right-to-left)的语言时,IMLangFontLink2接口来将字符串分解为块,将会失败。

以下代码应该是windows文本输出的终极方案

#inlucde <usp10.h>

HRESULT TextOutUniscribe(HDC hdc, int x, int y, LPCWSTR psz, int cch)
{
  if (cch == 0) return S_OK;
  SCRIPT_STRING_ANALYSIS ssa;
  HRESULT hr = ScriptStringAnalyse(hdc, psz, cch, 0, -1, SSA_FALLBACK | SSA_GLYPHS, MAXLONG, NULL, NULL, NULL, NULL, NULL, &ssa);
  if (SUCCESS(hr))
  {
    hr = ScriptString(ssa, x, y, 0, NULL, 0, 0, FALSE);
    ScriptStringFree(&ssa);
  }
  return hr;
}

9宫格背景图在缩放时的拉伸规则

1、关于资源:提供1x,2x……等多套资源

2、资源的使用规则:<150%,使用1x资源;<250%,使用2x资源;<350%,使用3x资源,以此类推

3、如果没有2x,3x资源,使用1x资源等比放大;所有配置数据,跟随倍率等比放大

4、背景显示大小,按缩放倍率平滑放大。即放大为125时,destSize = sourceSize * 125%

5、文字显示大写与上条规则相同

===========================

图片初始化规则:

1、如果缩放倍率发生了更改,判断是否需要重新载入资源

2、判断是否需要重新创建显示缓存