讓我們寫一個 Win32 文本編輯器吧 - 1. 簡介


讓我們寫一個 Win32 文本編輯器吧 - 1. 簡介

在之前的一篇文章 《曾經我認為C語言就是個弟弟》 中,我們通過使用 Windows 系統自帶的 EDIT 控件,創建了一個簡單的文本編輯器。而且在文章的最后,還承諾要不使用 EDIT 控件,自己制作一個十六進制編輯器。

后來想到,既然十六進制編輯器都做了,作為一個程序員,不如寫一個文本編輯器吧,既可以編輯二進制,又可以編輯文本,豈不美哉。

由於實現一個編輯器的復雜性相對比較大,一篇內容肯定完不成。所以,這里決定將整個過程作為一個系列來編輯。

本篇是系列的第一篇。在本篇文章中,將會對我們期望獲得的結果進行簡單的描述,並進行基礎代碼框架進行構建。

本文主要包含兩個部分,如下:

  1. 項目簡介

在項目簡介部分,將會對我們要實現的目標編輯器的樣子,以及使用方法進行介紹。同時,也會對本系列接下來的文章要討論的主題進行大致說明。

  1. 基礎代碼框架搭建

在代碼框架搭建部分,將會對項目的創建,設置進行說明。並編輯我們的基礎代碼。

1. 項目簡介

a. 目標

Windows11 中,已經將記事本的編輯控件由 EDIT 替換為 RichEditD2DPT,詳情參考Windows 11 Notepad。但是由於關於 RichEditD2DPT 控件的描述太少,不知道其具體的用方法。
所以,這里我們以 EDIT 控件的接口為准,並實現附加功能。

在此,我們的目標是:通過 C 語言,調用 Win32 接口,生成一個文本編輯器。目標編輯器除了實現和 Windows 提供的默認文本編輯器 EDIT所有消息處理,還提供如下功能:

  1. 可以設置字體顏色

    對於 EDIT 控件,雖然可以設置其文本字體,但是沒有設置顏色的方法。

  2. 可以編輯比較大的文件

    對於平時的文件編輯器來說,編輯小文件基本上都差不多,但是當遇到比較大的文件時(比如1G),很可能無能為力,甚至卡死。
    所以,既然我們要做一個新的編輯器,自然要考慮大文件的編輯問題。

  3. 采取Direct Write方式實現,而不是和普通的編輯器一樣,通過 GDI

    做此選擇的原因,除了因為 Direct Write 支持顏色之外,還有一些其它優點,詳情可以點擊Direct Write進行參考。

  4. 支持 EDIT控件 的所有消息。

    為了使得舊 Win32 代碼更好的使用本編輯器,所有 EDIT 控件支持的操作,本項目都應該支持。

  5. 處理\r\n

    此選擇和Windows 11中的選擇具有相同的理由,為了更好的處理換行。

  6. 支持撤銷操作/恢復上一步操作

    在編輯文本時,難免會想恢復到不久之前的版本,撤銷操作允許你做到這個。而當你后悔撤銷的時候,也應該能夠恢復到最新版本,恢復上一步允許你做到重新執行你之前的操作。

  7. 支持 Unicode 編碼

  8. 可以設置注解

    在編輯時,尤其是要編輯二進制文件時,我們有時候可能要對某個字節,或某段文本進行注解。我們的編輯器允許提供一個注解結構,以在顯示文檔時,可以進行注解顯示。

  9. 可以進行二進制文件編輯。

    二進制編輯雖然不常用,但是,不能在需要用的時候找不到。所以,這里提供了二進制編輯功能。此功能和注解相結合,就可以進行輔助二進制文件的分析。

b. 目標編輯器的樣子

作為一個現代的編輯器,我們希望它有一般編輯器都應該有的能力,下面是一個編輯器的例子:
![](https://img2022.cnblogs.com/blog/456172/202204/456172-20220403204453442-1758134648.png)

不難看到,作為一個編輯器,應該支持行號,高亮,多字體,滾動條等內容。這在我們的編輯器中,都將一一實現,並詳細描述實現過程。

c. 項目結構

對於本項目來說,一共包含兩個子項目,如下:

  • vicapp:
    用於對編輯器控件進行調用的樣例程序
  • vitality-controls:
    編輯器控件的實現項目,將作為一個 DLL 文件提供給調用者。

d. 參考鏈接

代碼地址:https://github.com/vitalitylee/vitality-controls

2. 基礎代碼框架搭建

接下來,我們詳細說明整個項目的構建過程。

a. 打開 Visual Studio ,並點擊創建新項目如下:

b. 在創建新項目對話框中,選擇空項目,並點擊下一步,如下:

c. 在配置新項目對話框中,設置項目內容,如下:

d. 右鍵項目vitality-conrols,並點擊屬性,彈出屬性對話框,如下:

e. 在常規選項卡中,設置配置類型為 動態庫,如下:


f. 一次點擊配置屬性->鏈接器->系統,並設置子系統窗口,如下:


g. 鼠標右鍵源文件文件夾,選擇添加->新建項,彈出添加新項對話框,如下:

注意,這里添加 .c文件,而不是 .cpp


h. 輸入 DLL 的入口代碼,如下:

#include <Windows.h>

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}

i. 添加預處理聲明

再次打開項目 vitality-controls 的屬性頁面,不難發現,比添加源文件之前,左側多了一個C/C++節點,左側依次選擇配置屬性->C/C++->預處理器選項,在右側的預處理器定義中,添加 VITALITY_CONTROLS_EXPORTS聲明,最終的值應為_DEBUG;VITALITY_CONTROLS_EXPORTS;_CONSOLE;%(PreprocessorDefinitions),如下圖所示:

j. 添加接口聲明文件

為了在兩個項目中公用一套代碼,新建的.h文件,放置在了解決方案根目錄下的shared-include目錄下,如下:

k. 修改接口代碼

向新建的vitality-controls.h文件中,輸入如下代碼:

#pragma once

#ifdef VITALITY_CONTROLS_EXPORTS
#define VIC_API __declspec(dllexport)
#else
#define VIC_API __declspec(dllimport)
#endif // VITALITY_CONTROLS_EXPORTS

#include <stdio.h>

VIC_API void vic_prints(const char* str);

並向main.c中添加新建的vitality-controls.h文件引用,並添加vic_prints函數實現,修改后代碼如下:

#include <Windows.h>

#include "../../shared-include/vitality-controls.h"

BOOL APIENTRY DllMain(HMODULE hModule,
    DWORD  ul_reason_for_call,
    LPVOID lpReserved
)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
    case DLL_THREAD_ATTACH:
    case DLL_THREAD_DETACH:
    case DLL_PROCESS_DETACH:
        break;
    }
    return TRUE;
}
  
VIC_API void vic_prints(const char* str) {
    puts(str);
}

l. 生成接口

鼠標右鍵解決方案,並點擊重新生成解決方案快捷菜單,如下:

最終,你將得到一個編譯好的vitality-controls.dll文件,如下:

m. 查看導出函數是否正常導出

點擊操作系統的開始菜單,並點擊Developer Command Prompt for VS XXXX,其中XXXX隨着你使用的Visual Studio 版本不同而不同,本文中使用的版本為Visual Studio 2022

所以,顯示如下:

點擊菜單后,會出現命令行窗口,在窗口中輸入命令cd/d [path]切換到目標文件所在目錄,其中[path]為你生成的目標 DLL 的所在目錄,如:

切換到目標目錄,就可以使用dumpbin查看導出函數。在命令行中輸入dumprin /exports vitality-controls.dll,看到如下內容,說明你生成成功了:

n. 新建測試項目

右鍵解決方案, 點擊菜單添加->新建項目,根據之前的步驟,添加一個新建項目 vicapp,添加主文件vicapp-main.c,並輸入如下代碼:

#include "../../shared-include/vitality-controls.h"

int main(int argc, char** argv) {
	vic_prints("hello vic.");
	return 0;
}

如下所示:

o. 設置啟動項目

右鍵 vicapp 項目,並點擊設為啟動項目菜單,如下:

設置完成后,點擊啟動按鈕,將默認啟動啟動項目

p. 添加項目引用

為了可以使得 vicapp 程序能夠引用到 vitality-controls.dll 目標文件,需要設置兩個項目之間的引用關系。

右鍵點擊 vicapp 項目,點擊快捷菜單添加->引用,彈出添加引用對話框,如下:


p. 運行程序

點擊Visual Studio本地 Windows 調試器按鈕,程序將啟動,並輸出 hello vic.,如下:

至此,我們項目的基礎結構已經搭建完成。

下篇文章,我們將首先實現控件的初始化,以及控件展示功能,並討論一下我們之后的項目計划,敬請期待。

讓我們寫一個Win32文本編輯器吧 系列文章,其代碼對應項目vitality-controls,主要對一個文本編輯器的實現過程進行說明。

如果要獲取到實時更新,歡迎微信掃描下方二維碼,關注微信公眾號編程之路漫漫,碼途求知己,天涯覓一心。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM