讓我們寫一個 Win32 文字編輯器吧 - 1. 簡介
在之前的一篇文章 《曾經我認為C語言就是個弟弟》 中,我們通過使用
Windows
系統自帶的EDIT
控制元件,建立了一個簡單的文字編輯器。而且在文章的最後,還承諾要不使用EDIT
控制元件,自己製作一個十六進位制編輯器。後來想到,既然十六進位制編輯器都做了,作為一個程式設計師,不如寫一個文字編輯器吧,既可以編輯二進位制,又可以編輯文字,豈不美哉。
由於實現一個編輯器的複雜性相對比較大,一篇內容肯定完不成。所以,這裡決定將整個過程作為一個系列來編輯。
本篇是系列的第一篇。在本篇文章中,將會對我們期望獲得的結果進行簡單的描述,並進行基礎程式碼框架進行構建。
本文主要包含兩個部分,如下:
- 專案簡介
在專案簡介部分,將會對我們要實現的目標編輯器的樣子,以及使用方法進行介紹。同時,也會對本系列接下來的文章要討論的主題進行大致說明。
- 基礎程式碼框架搭建
在程式碼框架搭建部分,將會對專案的建立,設定進行說明。並編輯我們的基礎程式碼。
1. 專案簡介
a. 目標
在
Windows11
中,已經將記事本的編輯控制元件由EDIT
替換為RichEditD2DPT
,詳情參考Windows 11 Notepad
。但是由於關於RichEditD2DPT
控制元件的描述太少,不知道其具體的用方法。
所以,這裡我們以EDIT
控制元件的介面為準,並實現附加功能。
在此,我們的目標是:通過 C
語言,呼叫 Win32
介面,生成一個文字編輯器。目標編輯器除了實現和 Windows
提供的預設文字編輯器 EDIT
的所有訊息處理,還提供如下功能:
-
可以設定字型顏色
對於
EDIT
控制元件,雖然可以設定其文字字型,但是沒有設定顏色的方法。 -
可以編輯比較大的檔案
對於平時的檔案編輯器來說,編輯小檔案基本上都差不多,但是當遇到比較大的檔案時(比如1G),很可能無能為力,甚至卡死。
所以,既然我們要做一個新的編輯器,自然要考慮大檔案的編輯問題。 -
採取
Direct Write
方式實現,而不是和普通的編輯器一樣,通過GDI
。做此選擇的原因,除了因為
Direct Write
支援顏色之外,還有一些其它優點,詳情可以點選Direct Write
進行參考。 -
支援
EDIT控制元件
的所有訊息。為了使得舊
Win32
程式碼更好的使用本編輯器,所有EDIT
控制元件支援的操作,本專案都應該支援。 -
處理
\r\n
此選擇和
Windows 11
中的選擇具有相同的理由,為了更好的處理換行。 -
支援撤銷操作/恢復上一步操作
在編輯文字時,難免會想恢復到不久之前的版本,撤銷操作允許你做到這個。而當你後悔撤銷的時候,也應該能夠恢復到最新版本,恢復上一步允許你做到重新執行你之前的操作。
-
支援
Unicode
編碼 -
可以設定註解
在編輯時,尤其是要編輯二進位制檔案時,我們有時候可能要對某個位元組,或某段文字進行註解。我們的編輯器允許提供一個註解結構,以在顯示文件時,可以進行註解顯示。
-
可以進行二進位制檔案編輯。
二進位制編輯雖然不常用,但是,不能在需要用的時候找不到。所以,這裡提供了二進位制編輯功能。此功能和註解相結合,就可以進行輔助二進位制檔案的分析。
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
,主要對一個文字編輯器的實現過程進行說明。
如果要獲取到實時更新,歡迎微信掃描下方二維碼,關注微信公眾號程式設計之路漫漫
,碼途求知己,天涯覓一心。