ウィンドウを作成することにより、MASMのマクロを使用します

2001年に、Win32でアセンブリ言語を学ぶのに多くの時間を費やしました。 次に、同じコードを100回書くことに苦労した後、マクロの小さなライブラリを自分で書くことにしました。 その結果、運命を十分に軽減し、必要に応じて1つのウィンドウで簡単なプログラムを作成して、膨大なコードを繰り返す必要を減らすことができました。

最近、私はそれらのプロジェクトに出会い、それらのいくつかをレイアウトすることに決めました。おそらく誰かが役に立つでしょう...



プロジェクト構成

それでは始めましょう。 このプロジェクトは、それが以下の構造を有する、以下に添付されています。

\マクロアプリケーションで使用されるマクロを含むカタログ
Macros.IncWin32プログラムを作成するときに必要な基本マクロを次に示します。 メモリの割り当て、ファイルの取り込みを容易にするマクロ、データを定義するマクロなどがここにあります。
Window.Macウィンドウの作成を簡単にするマクロ
Status.Mac行ステータスを作成および使用するためのマクロ
Menu.Macメニューを作成および使用するためのマクロ
Quake.Bmpプログラムウィンドウにロードされ、表示される画像
Scull.Ico画像アイコン(単なる破片)
Rsrc.rcリソース定義ファイル
Window.Asmメインプログラムファイル
Window.Exeコンパイルされたプログラム
WndExample.Asmこのファイルには、プログラムの「例」ウィンドウに来るメッセージを処理するためのソースコードが含まれています

Window.Exeを起動すると、表示されるウィンドウは次のようになります。

画像

最も単純なプログラム、ウィンドウなし


include macros\macros.inc @Start @Uses kernel32 .code WinMain Proc invoke ExitProcess, 0 WinMain Endp End WinMain 


ここの最初の行は、メインマクロ、そしてプログラムの開始を作成し、メモリモデル、使用されているプロセッサなどに関する情報を作成する開始マクロを含みます。 次のマクロが来る使用し 、それはプログラムに必要なライブラリが含まれています。 この場合、使用するExitProcessプロセスの終了に使用される関数が含まれているため、kernel32.dllを使用します。

以下は、メインプログラムプロシージャを含む.codeを使用して指定されたコードブロックです。 実際、プロシージャ自体は好きなように呼び出すことができ、ブルドーザーからWinMainという名前を付けました。 主なことは 、ファイルの最後にEnd{Input_function_name_name}があることです

このプログラムには機能的な負荷はありませんので、起動後は何もしません-ただ作業を終了します。 アーカイブ内のプログラムのソースコード:
 include macros\macros.inc IDC_MAINSTATUS Equ 1 IDC_MENUEXIT Equ 10 @Start @Uses gdi32, user32, comctl32, kernel32 .xlist include macros\Menu.mac include macros\Window.mac include macros\Status.mac .list .data? hIcon Dd ? hBrush Dd ? hCursor Dd ? hImage Dd ? hInstance Dd ? @DefineMenu Menu @DefineStatus Example @DefineWindow Example .code ; Main program cycle WinMain Proc mov hInstance, @Result(GetModuleHandle, NULL) mov hIcon, @Result(LoadIcon, hInstance, 100) mov hCursor, @Result(LoadCursor,NULL,IDC_ARROW) mov hBrush, @Result(GetSysColorBrush, COLOR_APPWORKSPACE) @CreateWindow Example, hInstance, NULL,'Example_wnd', \ WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_VISIBLE, \ WS_EX_APPWINDOW, 'Example', \ hIcon, hBrush, hCursor, NULL @SetWndSize Example, 700, 600 @MoveWnd Example, 100, 100 @CreateMenu Menu @AppendMenu Menu, 'Exit', IDC_MENUEXIT @AttachMenu Example, Menu @CreateStatus Example, Example, IDC_MAINSTATUS @SetStatusParts Example, 2,300,-1,0,0,0,0,0,0,0,0 @SetStatusText Example, 'Example program window...', 0, 0 @SetStatusText Example, 'The CHEMI$T Copyright(C)2001', 0, 1 @ProcessMsgs Example, FALSE @DestroyMenu Menu @DestroyWindow Example invoke ExitProcess, 0 WinMain Endp End WinMain '、 include macros\macros.inc IDC_MAINSTATUS Equ 1 IDC_MENUEXIT Equ 10 @Start @Uses gdi32, user32, comctl32, kernel32 .xlist include macros\Menu.mac include macros\Window.mac include macros\Status.mac .list .data? hIcon Dd ? hBrush Dd ? hCursor Dd ? hImage Dd ? hInstance Dd ? @DefineMenu Menu @DefineStatus Example @DefineWindow Example .code ; Main program cycle WinMain Proc mov hInstance, @Result(GetModuleHandle, NULL) mov hIcon, @Result(LoadIcon, hInstance, 100) mov hCursor, @Result(LoadCursor,NULL,IDC_ARROW) mov hBrush, @Result(GetSysColorBrush, COLOR_APPWORKSPACE) @CreateWindow Example, hInstance, NULL,'Example_wnd', \ WS_OVERLAPPED+WS_CAPTION+WS_SYSMENU+WS_VISIBLE, \ WS_EX_APPWINDOW, 'Example', \ hIcon, hBrush, hCursor, NULL @SetWndSize Example, 700, 600 @MoveWnd Example, 100, 100 @CreateMenu Menu @AppendMenu Menu, 'Exit', IDC_MENUEXIT @AttachMenu Example, Menu @CreateStatus Example, Example, IDC_MAINSTATUS @SetStatusParts Example, 2,300,-1,0,0,0,0,0,0,0,0 @SetStatusText Example, 'Example program window...', 0, 0 @SetStatusText Example, 'The CHEMI$T Copyright(C)2001', 0, 1 @ProcessMsgs Example, FALSE @DestroyMenu Menu @DestroyWindow Example invoke ExitProcess, 0 WinMain Endp End WinMain 


次に、このソースで何が起こっているのかを段階的に説明します。 最初はマクロメニュー、ステータスバー、およびウィンドウの機能の実装が含まれています。 これらは、マクロアセンブラーの特別なコマンド.xlist (リストを無効にする)および.list (リストを有効にする)で囲まれています。これは、リストがマクロアセンブラーによって発行された場合、これらのファイルからコードがなかったためです/追加のコードタオルのみ/以下は初期化されていないブロックの説明です.data data 、このブロックの変数は初期化されず、システムはメモリをリセットせずに単に割り当てます。 何でもメモリに保存できるため、初期化せずにそのような変数を使用するのは困難です。 ここでは、変数にスペースが割り当てられ、WinMainメソッドの最初の行で、ロードされたリソースとアプリケーション自体のインスタンスの値を取得します。
マクロ@ DefineMenu、@ DefineStatusおよび@DefineWindowは、オブジェクト/メニューのパラメーター、行のステータス、ウィンドウのステータスがそれぞれ格納される変数を初期化します/
そして、すべての初期化の後、最も興味深いことが起こります。
最初の4行
  mov hInstance, @Result(GetModuleHandle, NULL) mov hIcon, @Result(LoadIcon, hInstance, 100) mov hCursor, @Result(LoadCursor,NULL,IDC_ARROW) mov hBrush, @Result(GetSysColorBrush, COLOR_APPWORKSPACE) 

アプリケーション/アイコン、カーソル、ブラシの変数/インスタンスを初期化して、ウィンドウ/を描画します。 素敵な結果マクロを使用します。 このマクロは、渡されたパラメーターを使用して指定されたAPI呼び出しを行い、関数の結果を返すEAXレジスターの内容を返します。 それはマクロがなければ、各ラインは、このようなコードに分割しました。
  invoke GetModuleHandle, NULL mov hInstance, eax 

ウィンドウの作成と操作のためのマクロは順番に呼び出す必要があります。@ CreateWindow-ウィンドウを作成します。@ SetWndSize-ウィンドウサイズを設定します。@ MoveWndはウィンドウを画面上の目的の座標に移動します。@ ProcessMsgsは、ウィンドウ。 ウィンドウを作成するとき、このウィンドウのイベントハンドラを含むファイルを作成する必要があります。 プロジェクトではWndExample.Asmファイルです。 この名前は、マスクWnd <window_name> .Asmによってイベントハンドラーファイルが自動的にオンになるように設定されます
メニューを作成し、ステータス行を作成するためのマクロは完了していませんでした。必要な機能のみを実行しました。
メニュー操作マクロ:
@CreateMenu {Menu_name}
目的の名前でメニューを作成します

@AppendMenu {Menu_name}、{Menu item_name header}、{Message_code}
目的のタイトルのメニュー項目を追加します。 メニュー項目メッセージコードをクリックするとメッセージキューを取得します。

Imya_okna @AttachMenu {}、{} MENUNAME
指定されたウィンドウにメニューを追加します。

ステータスバーで動作するマクロ/ / COMCTL32が必要
@CreateStatus {String_StatusName}、{Window_Name}、{String_Status ID}
指定されたウィンドウの行ステータスを作成する

@SetStatusParts {String_Status_name}、{Number of_parts}、{Part_width}、{}、{}、{}、{} /最大10パート、最後は指定されたサイズ= -1、つまり ストレッチ/
いくつかの部分に分けて、このマクロを完成させることはできましたが、どういうわけか、私はそれをやらなかったようです

@SetStatusText {String_Status_name}、{Text}、{Style /理由がわからない/}、{String_status_part}
ステータスをステータス行の目的の部分に設定する


イベントハンドラファイル

このファイルは、ユーザー定義ハンドラーが登録され、メニューイベントハンドラーも登録する必要があるメインウィンドウプロシージャのソースコードを指定します。 各ウィンドウイベントハンドラは次のようになります。
Imya_okna @WndHandlerStart {}、{} Imya_obrabotchika

mov eax、TRUE
Imya_okna @WndHandlerEnd {}、{} Imya_obrabotchika

上記のプロジェクトの主な手順はファイルの最後にあり、次のようになります。
 @WndProcedureBegin Example, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT ; Menu handlers @WndMenuHandler IDC_MENUEXIT, Exit ; Sample user handler @WndUserHandler Example, WM_SIZING @WndProcedureEnd Example 

ここでは、Exitという名前のMessage_Code IDC_MENUEXITハンドラーが割り当てられているメニュー項目ハンドラーが割り当てられています。 また、ユーザーハンドラWM_SIZINGポストを登録。 カスタムイベントハンドラは、それが処理するメッセージの名前を持っている必要があります。 ウィンドウで事前定義されているすべてのイベントは、@ WndProcedureBeginマクロのWindow.Macファイルで表示できます。 これらのイベントのリストは、Close、Paint、Help、Activate、Deactivate、SysCommand、Show、Hide、Create、Destroy、KeyDown、KeyUp、Resize、DblClick、MouseUp、MouseDown、WheelDown、WheelUpです。 これらのハンドラーの例はプロジェクトソースに含まれており、ウィンドウでF1をクリックしてマウスホイールを回転できます。

原則として、これらのイベントに関連するすべてのものはMSDNおよびソースで表示できます。複雑なことは何もないので、この説明には含めません。


プログラムのコンパイル


コンパイルにはmasm32パッケージが必要です( こちらをご覧ください )。インストール後、パスをmasm32 \ binディレクトリに追加してPath環境変数に追加し、mlコンパイラーとリンカーの呼び出しを修正してmasm32 / bin / build.batファイルを編集して、ライブラリパスとインクルードファイルを追加することをお勧めしますコードにパスデータを常に登録する必要がありました。

したがって、ML.Exeの呼び出しでは、別のパラメーター/ IFを追加する必要があります。IF:\ masm32 \ include-F:\ masm32の代わりに、masm32パッケージをインストールしたパスを指定する必要があります。 また、Link.exeリンカーの2つの呼び出しで、/ LIBPATHオプションを使用してライブラリパスを追加する必要があります:F:\ masm32 \ lib。 繰り返しますが、パスを自分のものに一致するパスに置き換えます。

次に、プロジェクトのあるディレクトリで、2つのコマンドbresbres.batは現在のディレクトリのリソースファイルrsrc.rcをコンパイルします)とビルドウィンドウbuild.bat-プロジェクトをコンパイルしてリンクします)を指定します。

GitHubに転送されたプロジェクト

Source: https://habr.com/ru/post/J107272/


All Articles