65.9K
CodeProject 正在变化。 阅读更多。
Home

破解 FontDialog

starIconstarIconstarIconstarIconstarIcon

5.00/5 (7投票s)

2008年8月23日

CPOL

2分钟阅读

viewsIcon

38030

downloadIcon

774

如何隐藏 FontDialog 的 UI 元素(例如,字体大小)。

引言

我们经常希望使用通用对话框(如字体对话框),但不希望用户选择对话框提供的所有属性,这是一个常见的问题。本文展示了我们如何做到这一点,以字体对话框为例。

背景

我确实需要一个没有字体大小属性的字体对话框,用于自动管理字体大小的绘图应用程序,所以我们不希望用户能够更改它。 有两种选择:

  1. 重写整个字体对话框。
  2. 破解它。

因为它提供了一个不错的字体预览,所以我决定采用第二种方法。

黑客技术

如果我们有要破解的窗口的句柄,整个问题就非常容易了。 应该添加一些本地函数调用,例如

[DllImport("user32.dll")]
static extern IntPtr GetDlgItem(IntPtr hDlg, int nIDDlgItem);

[DllImport("user32.dll")]
static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

const int SW_HIDE = 0

通用对话框的每个 UI 组件都有一个固定的 ID。 Spy++ 可以帮助我们识别它们。 对于字体大小,这些 ID 是 1090 和 1138;因此,我们可以通过调用来隐藏不需要的组件

ShowWindow(GetDlgItem(dialogHandle, 1090), SW_HIDE);
ShowWindow(GetDlgItem(dialogHandle, 1138), SW_HIDE);

查找对话框句柄

关键问题是识别 dialogHandle。 示例展示了三种可能的解决方案,其中两种很流行,但存在自身的问题。

  • FindWindow:让我们在使用 FindWindow() 本地调用显示字体对话框之后找到它。 在显示对话框之前,启动一个计时器,如果在找到对话框时完成。 这种方法存在以下问题
    • 计时器的正确间隔是多少? 如果选择大量时间,用户可以看到不需要的 UI 元素,这些元素稍后会消失。
    • FindWindow 将窗口的标题作为输入参数。 如果 Windows 不是英文,字体对话框的标题不是“字体”。
    • 如果它找不到正确的对话框,它将继续运行到永远。
  • GetActiveWindow:让我们假设活动窗口是我们的字体对话框; 再次,在显示之前启动一个计时器,并希望计时器第一次触发时字体对话框将成为活动窗口。 同样,正确的计时器间隔是未知的,如果我们的字体对话框碰巧不是最顶层的,我们会向另一个应用程序发送命令。
  • 最佳解决方案:让我们采用本文中描述的方法:在 .NET 中自定义 OpenFileDialog

我从中删除了所有不需要的代码,以获得我们问题的简单解决方案。 FontDialogEx 类将代替 FontDialog 使用。 它的 ShowDialog 方法创建一个名为 DummyForm 的虚拟的、不可见的窗体。 通过设置名为 UFLAGSHIDE 的标志来实现不可见性。 DummyForm 等待直到它被激活,这可以在它重写的 WndProc(ref Message m) 函数中找到。

protected override void WndProc(ref Message m)
{
  if (mWatchForActivate && m.Msg == (int)Win32.WM_ACTIVATE)
  {
    mWatchForActivate = false;
    mFontDialogHandle = m.LParam;
    mNativeDialog = new FontDialogNative(m.LParam, mFileDialogEx);
  }
  base.WndProc(ref m);
}

这是我们可以找到字体对话框句柄的地方。 在找到正确的句柄后创建 FontDialogNative,因此我们不需要的 UI 元素可以在 FontDialogNative 的构造函数中隐藏。

历史

这是 Font Dialog 破解的第一个版本。

© . All rights reserved.