【WPF高仿 Windows记事本】开发日记 (六) 自动换行、滚动条命令绑定,实现字体模式的选择功能(格式菜单功能实现)

在这里插入图片描述

前言

作者:浪子花梦,一个有趣的程序员 ~
此文章将完成 格式菜单中的所有功能:自动换行的一些绑定、字体的选择功能

前文如下所示:
【WPF高仿 Windows记事本】开发日记 (一) UI布局(帮助菜单功能实现)
【WPF高仿 Windows记事本】开发日记 (二) 初步使用MVVM模式设计 帮助菜单 的三个命令
【WPF高仿 Windows记事本】开发日记 (三) 完善所有菜单的命令绑定并创建Models层的设计
【WPF高仿 Windows记事本】开发日记 (四) 菜单命令快捷键实现,实现查看菜单功能(三层架构初步使用
【WPF高仿 Windows记事本】开发日记 (五) 使用成熟的自动更新代码(ObservableObject)、实现是否显示状态栏功能、鼠标的滚轮命令绑定(查看菜单功能实现)

此文章的实现效果如下所示:

格式菜单功能实现


1)DocumentModel 数据层 数据准备,用于记录当前是否自动换行,也用于滚动条的绑定:
在这里插入图片描述

.
.

2)多值转换器的准备,分别将 Boolean类型转换为TextWrapping,ScrollBarVisibility 类型:
在这里插入图片描述
BooleanScrollBarVisibilityConverter 类的代码如下所示:
在这里插入图片描述
BooleanTextWrappingConverter 类的代码如下所示:
在这里插入图片描述

.
.

3)UI 层进行数据的绑定:
绑定菜单上面的数据:
在这里插入图片描述
对文本框的属性进行绑定(自动换行,滚动条):
在这里插入图片描述
自动换行的菜单功能已经实现 . . .

.
.

4)实现字体菜单的功能,Win32API 准备:
在这里插入图片描述
需要定义这个API,我们还需要其它的一些数据的定义,代码如下所示:

// if we specify CharSet.Auto instead of CharSet.Ansi, then the string will be unreadable
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public class LOGFONT
{
    public int lfHeight;
    public int lfWidth;
    public int lfEscapement;
    public int lfOrientation;
    public FontWeight lfWeight;
    [MarshalAs(UnmanagedType.U1)]
    public bool lfItalic;
    [MarshalAs(UnmanagedType.U1)]
    public bool lfUnderline;
    [MarshalAs(UnmanagedType.U1)]
    public bool lfStrikeOut;
    public FontCharSet lfCharSet;
    public FontPrecision lfOutPrecision;
    public FontClipPrecision lfClipPrecision;
    public FontQuality lfQuality;
    public FontPitchAndFamily lfPitchAndFamily;
    [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 32)]
    public string lfFaceName;

    public override string ToString()
    {
        StringBuilder sb = new StringBuilder();
        sb.Append("LOGFONT\n");
        sb.AppendFormat("   lfHeight: {0}\n", lfHeight);
        sb.AppendFormat("   lfWidth: {0}\n", lfWidth);
        sb.AppendFormat("   lfEscapement: {0}\n", lfEscapement);
        sb.AppendFormat("   lfOrientation: {0}\n", lfOrientation);
        sb.AppendFormat("   lfWeight: {0}\n", lfWeight);
        sb.AppendFormat("   lfItalic: {0}\n", lfItalic);
        sb.AppendFormat("   lfUnderline: {0}\n", lfUnderline);
        sb.AppendFormat("   lfStrikeOut: {0}\n", lfStrikeOut);
        sb.AppendFormat("   lfCharSet: {0}\n", lfCharSet);
        sb.AppendFormat("   lfOutPrecision: {0}\n", lfOutPrecision);
        sb.AppendFormat("   lfClipPrecision: {0}\n", lfClipPrecision);
        sb.AppendFormat("   lfQuality: {0}\n", lfQuality);
        sb.AppendFormat("   lfPitchAndFamily: {0}\n", lfPitchAndFamily);
        sb.AppendFormat("   lfFaceName: {0}\n", lfFaceName);

        return sb.ToString();
    }
}

public enum FontWeight : int
{
    FW_DONTCARE = 0,
    FW_THIN = 100,
    FW_EXTRALIGHT = 200,
    FW_LIGHT = 300,
    FW_NORMAL = 400,
    FW_MEDIUM = 500,
    FW_SEMIBOLD = 600,
    FW_BOLD = 700,
    FW_EXTRABOLD = 800,
    FW_HEAVY = 900,
}
public enum FontCharSet : byte
{
    ANSI_CHARSET = 0,
    DEFAULT_CHARSET = 1,
    SYMBOL_CHARSET = 2,
    SHIFTJIS_CHARSET = 128,
    HANGEUL_CHARSET = 129,
    HANGUL_CHARSET = 129,
    GB2312_CHARSET = 134,
    CHINESEBIG5_CHARSET = 136,
    OEM_CHARSET = 255,
    JOHAB_CHARSET = 130,
    HEBREW_CHARSET = 177,
    ARABIC_CHARSET = 178,
    GREEK_CHARSET = 161,
    TURKISH_CHARSET = 162,
    VIETNAMESE_CHARSET = 163,
    THAI_CHARSET = 222,
    EASTEUROPE_CHARSET = 238,
    RUSSIAN_CHARSET = 204,
    MAC_CHARSET = 77,
    BALTIC_CHARSET = 186,
}
public enum FontPrecision : byte
{
    OUT_DEFAULT_PRECIS = 0,
    OUT_STRING_PRECIS = 1,
    OUT_CHARACTER_PRECIS = 2,
    OUT_STROKE_PRECIS = 3,
    OUT_TT_PRECIS = 4,
    OUT_DEVICE_PRECIS = 5,
    OUT_RASTER_PRECIS = 6,
    OUT_TT_ONLY_PRECIS = 7,
    OUT_OUTLINE_PRECIS = 8,
    OUT_SCREEN_OUTLINE_PRECIS = 9,
    OUT_PS_ONLY_PRECIS = 10,
}
public enum FontClipPrecision : byte
{
    CLIP_DEFAULT_PRECIS = 0,
    CLIP_CHARACTER_PRECIS = 1,
    CLIP_STROKE_PRECIS = 2,
    CLIP_MASK = 0xf,
    CLIP_LH_ANGLES = (1 << 4),
    CLIP_TT_ALWAYS = (2 << 4),
    CLIP_DFA_DISABLE = (4 << 4),
    CLIP_EMBEDDED = (8 << 4),
}
public enum FontQuality : byte
{
    DEFAULT_QUALITY = 0,
    DRAFT_QUALITY = 1,
    PROOF_QUALITY = 2,
    NONANTIALIASED_QUALITY = 3,
    ANTIALIASED_QUALITY = 4,
    CLEARTYPE_QUALITY = 5,
    CLEARTYPE_NATURAL_QUALITY = 6,
}
[Flags]
public enum FontPitchAndFamily : byte
{
    DEFAULT_PITCH = 0,
    FIXED_PITCH = 1,
    VARIABLE_PITCH = 2,
    FF_DONTCARE = (0 << 4),
    FF_ROMAN = (1 << 4),
    FF_SWISS = (2 << 4),
    FF_MODERN = (3 << 4),
    FF_SCRIPT = (4 << 4),
    FF_DECORATIVE = (5 << 4),
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
public struct CHOOSEFONT
{
    public int lStructSize;
    public IntPtr hwndOwner;
    public IntPtr hDC;
    public IntPtr lpLogFont;
    public int iPointSize;
    public int Flags;
    public int rgbColors;
    public IntPtr lCustData;
    public IntPtr lpfnHook;
    public string lpTemplateName;
    public IntPtr hInstance;
    public string lpszStyle;
    public short nFontType;
    private short __MISSING_ALIGNMENT__;
    public int nSizeMin;
    public int nSizeMax;
}

[Flags]
public enum CHOOSEFONTFLAGS
{
    CF_SCREENFONTS = 0x00000001,
    CF_PRINTERFONTS = 0x00000002,
    CF_BOTH = (CF_SCREENFONTS | CF_PRINTERFONTS),
    CF_SHOWHELP = 0x00000004,
    CF_ENABLEHOOK = 0x00000008,
    CF_ENABLETEMPLATE = 0x00000010,
    CF_ENABLETEMPLATEHANDLE = 0x00000020,
    CF_INITTOLOGFONTSTRUCT = 0x00000040,
    CF_USESTYLE = 0x00000080,
    CF_EFFECTS = 0x00000100,
    CF_APPLY = 0x00000200,
    CF_ANSIONLY = 0x00000400,
    CF_SCRIPTSONLY = CF_ANSIONLY,
    CF_NOVECTORFONTS = 0x00000800,
    CF_NOOEMFONTS = CF_NOVECTORFONTS,
    CF_NOSIMULATIONS = 0x00001000,
    CF_LIMITSIZE = 0x00002000,
    CF_FIXEDPITCHONLY = 0x00004000,
    CF_WYSIWYG = 0x00008000,
    CF_FORCEFONTEXIST = 0x00010000,
    CF_SCALABLEONLY = 0x00020000,
    CF_TTONLY = 0x00040000,
    CF_NOFACESEL = 0x00080000,
    CF_NOSTYLESEL = 0x00100000,
    CF_NOSIZESEL = 0x00200000,
    CF_SELECTSCRIPT = 0x00400000,
    CF_NOSCRIPTSEL = 0x00800000,
    CF_NOVERTFONTS = 0x01000000,
    CF_INACTIVEFONTS = 0x02000000
}

.
.

5)DocumentModel 数据层的数据准备:
在这里插入图片描述
.
.

6)UI层的文本框与数据层作绑定:
在这里插入图片描述
.
.

7)字体命令实现(OnFontCommand):

private void OnFontCommand()
{
    FontStyle fontStyle = FontStyle.Regular;

    // 获取当前字体的风格、宽度
    if (DocumentModel.FontStyle == "Italic") { fontStyle |= FontStyle.Italic; }
    if (DocumentModel.FontWeight == "Bold") { fontStyle |= FontStyle.Bold; }

    // 以当前字体代表的信息生成一种字体
    Font font = new Font(DocumentModel.FontFamily, (float)DocumentModel.FontSize, fontStyle, GraphicsUnit.World, 0, false);
    LOGFONT logfont = new LOGFONT();
    font.ToLogFont(logfont);

    IntPtr pLogfont = Marshal.AllocHGlobal(Marshal.SizeOf(logfont));
    Marshal.StructureToPtr(logfont, pLogfont, false);

    CHOOSEFONT choosefont = new CHOOSEFONT();
    choosefont.lStructSize = Marshal.SizeOf(choosefont);
    choosefont.hwndOwner = Process.GetCurrentProcess().MainWindowHandle;
    choosefont.nSizeMin = 64;
    choosefont.nSizeMax = 64;
    choosefont.Flags = (int)CHOOSEFONTFLAGS.CF_SCREENFONTS
                     | (int)CHOOSEFONTFLAGS.CF_INITTOLOGFONTSTRUCT
                     | (int)CHOOSEFONTFLAGS.CF_FORCEFONTEXIST
                     | (int)CHOOSEFONTFLAGS.CF_NOVERTFONTS;
    choosefont.lpLogFont = pLogfont;
    choosefont.nFontType = 0x2000;

    IntPtr pChoosefont = Marshal.AllocHGlobal(Marshal.SizeOf(choosefont));
    Marshal.StructureToPtr(choosefont, pChoosefont, false);

    // 显示字体对话框 
    bool result = Win32Helper.ChooseFont(pChoosefont);
    if (result)
    {
        // 从非托管内存中获取字体的结构体信息
        LOGFONT logfont1 = (LOGFONT)Marshal.PtrToStructure(pLogfont, typeof(LOGFONT));
        Font font1 = Font.FromLogFont(logfont1);        // 以Font对象表示

        // 更新当前改变过后的数据
        DocumentModel.FontFamily = font1.Name;
        DocumentModel.FontSize = font1.Size;
        DocumentModel.FontStyle = "Normal";
        DocumentModel.FontWeight = "Normal";

        // 判断是否是斜体
        if ((font1.Style & FontStyle.Italic) != 0) { DocumentModel.FontStyle = "Italic"; }
        // 判断是否加粗
        if ((font1.Style & FontStyle.Bold) != 0) { DocumentModel.FontWeight = "Bold"; }
    }

    // 释放内存
    Marshal.FreeHGlobal(pChoosefont);
    Marshal.FreeHGlobal(pLogfont);
}

至此,格式菜单的功能已经实现 . . .

猜你喜欢

转载自blog.csdn.net/weixin_42100963/article/details/107566921