インターネットから収集したもので、参照のみを目的としています
実験 3 では 2 つの完全なレポートが収集されました。1 つはこれで、もう 1 つはこのコラムの次の記事に記載されています。
実験テーマ
「オブジェクト指向プログラミング」実験3
実験トピック: サブウィンドウとコントロールの基本的な使用法、リソースの使用法
全体的な目的: ウィンドウ間のメッセージ転送、コール スタックを理解する; カーソル、アイコン、メニューの作成および使用方法を習得する; メニューへの応答方法、ショートカット メニューの読み込み方法および使用方法を習得する; GetWindowLong/SetWindowLong、GetClassLong/SetClassLong 関数を理解する使用法。
実験的なコンテンツのプロセス:
ChildWin サンプルプログラムを改良し、サブウィンドウにウィンドウ固有の情報(ウィンドウ ID 番号)を表示するようにし、各サブウィンドウに特定の色の四角形を描画するようにしました。
-
- 子ウィンドウのウィンドウプロシージャ関数のリフレッシュ処理メッセージに処理コードを追加します。
- GetWindowLong 関数を使用して子ウィンドウ ID を取得します。
- サブウィンドウIDに応じてサブウィンドウに表示する情報を設定します(wsprintf関数を使用して表示する文字列を整理します)
- 子ウィンドウに特定の色の四角形を描画してみます (CreateSolidBrush、Rectangle 関数を使用)
- メッセージングプロセスを追跡する
- Childwin のメイン ウィンドウ プロセス関数の WM_CREATE、WM_PAINT、WM_COMMAND、WM_LBUTTONDOWN にブレークポイントを設定します。
- 子ウィンドウの WM_CREATE、WM_PAINT、WM_CHILDWIN、WM_LBUTTONDOWN にブレークポイントを設定します。
- プログラムを実行し、各ブレークポイントの応答プロセスを表示して、メッセージ配信の順序を理解します。
- ソフトキーボードの設計と実装
サブウィンドウを使用してソフト キーボードを実装し (ウィンドウのクライアント領域にサブウィンドウでシミュレートされたキーボードを描画します)、各サブウィンドウをマウスでクリックしてさまざまな文字を入力します。入力した文字をウィンドウ内に表示します。
- コントロール テスト用に独自の作業ディレクトリに新しいプロジェクトを作成します (Easywin プロジェクトの easywin.c を新しいプロジェクトのディレクトリにコピーし、ファイル名を ctltest.cpp に変更し (サフィックスを .cpp に変更します)、コンパイルし、リンクしてプログラムを動作させる (コンパイル エラーの修正を含む)]。
- * ボタンを使用して、4* で必要なソフト キーボードを完成させます。元の実装との違いを比較してください。
- 静的、編集、リストボックス、コンボボックス、ボタン、スクロールバーなどのさまざまなタイプのコントロールサブウィンドウを作成し、メインウィンドウのウィンドウプロシージャ関数に対応するメッセージ処理を追加して、メインウィンドウとサブウィンドウ間の通信を実現します。ウィンドウ (コントロールのタイトル/コンテンツを設定し、コントロールのタイトル/コンテンツを取得して、コントロールがクリックなどの操作を行ったときにメイン ウィンドウにプロンプトを表示してみます)。
- 手順 5 と同様に、リソース テスト用の新しいプロジェクトを作成します。
- 新しいリソースの追加: カーソル、アイコン、および正しく表示される
- リソースエディタを使用してカーソル(色)を編集し、リソース内の不要な画像タイプを削除しないと、カーソルが正しく表示されない可能性がありますので注意してください。
- カーソルのホットスポットを設定します(ホットスポット)
- リソースエディターでアイコンを編集する
- プログラムがカスタム カーソルとアイコンを正常に使用できるように、登録されたウィンドウ クラスのコードを変更します。
- DrawIcon関数を使用してWM_PAINTメッセージに処理を追加し、ウィンドウのクライアント領域にカスタムカーソルとアイコンを表示します。
- 後続の実験手順で使用する追加のカーソルを作成します。
- メニューを追加
- ウィンドウで使用されるカーソルを変更するメニュー項目コマンドをメニューに作成します。このコマンドには「ChangeCursor」という名前を付けることができ、対応する ID は ID_CHANGECURSOR であると想定されます。
- プログラムの実行時にメニューが正しくロードされるように、登録されたウィンドウ クラスのコードを変更します。
- 別の方法では、ウィンドウを作成するコード ( CreateWindow )を変更することで、メニューを正しく読み込むことができます。
- メニューメッセージ応答コードを追加
- WM_COMMAND メッセージの処理を増やす
- 5章のメニューサンプルコードの処理方法を参照してメニューコマンドに応答してください。
- ID_CHANGECURSOR コマンドに対する応答は次のとおりです。ウィンドウで使用されるカーソルを変更するには、 SetClassLong (hwnd, GCL_HCURSOR,
(LONG)LoadCursor((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDC_CURSOR2) ) ); を使用できます。
- マウスの右ボタンの処理、ショートカットメニュー処理の追加
- 右ボタンで発行されたメニュー コマンドも WM_COMMAND メッセージで応答されるため、ショートカット メニューを追加すると、プログラムはメイン メニューまたはショートカット メニューから同じコマンドを発行できるようになります。
- プログラム構築に使用するバッチファイルに、この実験で完了したプロジェクトのコンパイルとリンクを追加し、そのバッチファイルを使用して実験 1、2、3 のすべてのプロジェクトを一度に自動ビルドします。
- この実験の実験レポート提出時間は10月22日21時30分までです。
知らせ:
- 5* オプション。
- 各実験のバックアップをしっかりと行い、各実験クラスでの将来の参照用に、以前の実験のすべての実験結果 (電子版) を携帯してください。
- 実験レポートの形式とファイル名は要件を満たしている必要があります。
実験レポート 1 (別のレポートについては、このコラムの次の記事を参照してください)
ウィンドウ間のメッセージ送信とコールスタックを理解する; カーソル、アイコン、およびメニューの作成と使用法を習得する; メニューの応答、ショートカット メニューのロードと使用法を習得する; GetWindowLong/SetWindowLong、GetClassLong/SetClassLong 関数の使用法を理解する。
2.実験の過程と結果
2.1 プロジェクトを作成する
- ChildWin サンプルプログラムを改良し、サブウィンドウにウィンドウ固有の情報(ウィンドウ ID 番号)を表示するようにし、各サブウィンドウに特定の色の四角形を描画するようにしました。
- 子ウィンドウのウィンドウプロシージャ関数のリフレッシュ処理メッセージに処理コードを追加します。
- GetWindowLong 関数を使用して子ウィンドウ ID を取得します。
- サブウィンドウIDに応じてサブウィンドウに表示する情報を設定します(wsprintf関数を使用して表示する文字列を整理します)
- 子ウィンドウに特定の色の四角形を描画してみます (CreateSolidBrush、Rectangle 関数を使用)
2. メッセージングプロセスを追跡する
WM_CREATE、WM_PAINT、WM_COMMAND、
-
- WM_LBUTTONDOWN にブレークポイントを設定します
- 子ウィンドウの WM_CREATE、WM_PAINT、WM_CHILDWIN、WM_LBUTTONDOWN にブレークポイントを設定します。
- プログラムを実行し、各ブレークポイントの応答プロセスを表示して、メッセージ配信の順序を理解します。
3. ソフトキーボードの設計と実装
サブウィンドウを使用してソフト キーボードを実装し (ウィンドウのクライアント領域にサブウィンドウでシミュレートされたキーボードを描画します)、各サブウィンドウをマウスでクリックしてさまざまな文字を入力します。入力した文字をウィンドウ内に表示します。
4. コントロール テスト用に独自の作業ディレクトリに新しいプロジェクトを作成します (Easywin プロジェクトの easywin.c を新しいプロジェクトのディレクトリにコピーし、ファイル名を ctltest.cpp に変更します (サフィックスを .cpp に変更します)。プログラムをコンパイル、リンクし、動作させる (コンパイル エラーの修正を含む)]
- * ボタンを使用して、4* で必要なソフト キーボードを完成させます。元の実装との違いを比較してください。
- 静的、編集、リストボックス、コンボボックス、ボタン、スクロールバーなどのさまざまなタイプのコントロールサブウィンドウを作成し、メインウィンドウのウィンドウプロシージャ関数に対応するメッセージ処理を追加して、メインウィンドウとサブウィンドウ間の通信を実現します。ウィンドウ (コントロールのタイトル/コンテンツを設定し、コントロールのタイトル/コンテンツを取得して、コントロールがクリックなどの操作を行ったときにメイン ウィンドウにプロンプトを表示してみます)。
- 手順 4 と同様に、リソース テスト用の新しいプロジェクトを作成します。
- 新しいリソースの追加: カーソル、アイコン、および正しく表示される
- リソースエディタを使用してカーソル(色)を編集し、リソース内の不要な画像タイプを削除しないと、カーソルが正しく表示されない可能性がありますので注意してください。
- カーソルのホットスポットを設定します(ホットスポット)
- リソースエディターでアイコンを編集する
- プログラムがカスタム カーソルとアイコンを正常に使用できるように、登録されたウィンドウ クラスのコードを変更します。
- DrawIcon関数を使用してWM_PAINTメッセージに処理を追加し、ウィンドウのクライアント領域にカスタムカーソルとアイコンを表示します。
- 後続の実験手順で使用する追加のカーソルを作成します。
9. メニューの追加
- メニューを追加
- ウィンドウで使用されるカーソルを変更するメニュー項目コマンドをメニューに作成します。このコマンドには「ChangeCursor」という名前を付けることができ、対応する ID は ID_CHANGECURSOR であると想定されます。
- プログラムの実行時にメニューが正しくロードされるように、登録されたウィンドウ クラスのコードを変更します。
- 別の方法では、ウィンドウを作成するコード ( CreateWindow )を変更することで、メニューを正しく読み込むことができます。
- メニューメッセージ応答コードを追加
- WM_COMMAND メッセージの処理を増やす
- 5章のメニューサンプルコードの処理方法を参照してメニューコマンドに応答してください。
- ID_CHANGECURSOR コマンドに対する応答は次のとおりです。ウィンドウで使用されるカーソルを変更するには、 SetClassLong (hwnd, GCL_HCURSOR,
(LONG)LoadCursor((HINSTANCE)GetWindowLong(hwnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDC_CURSOR2) ) ); を使用できます。
- マウスの右ボタンの処理、ショートカットメニュー処理の追加
右ボタンで発行されたメニュー コマンドも WM_COMMAND メッセージで応答されるため、ショートカット メニューを追加すると、プログラムはメイン メニューまたはショートカット メニューから同じコマンドを発行できるようになります。
- プログラム構築に使用するバッチファイルに、この実験で完了したプロジェクトのコンパイルとリンクを追加し、そのバッチファイルを使用して実験 1、2、3 のすべてのプロジェクトを一度に自動ビルドします。
2.3問題点と解決策
- メインウィンドウに設定したカーソルをサブウィンドウに表示することはできないので、独自のカーソルをサブウィンドウに設定するには、グローバル変数を使用してサブウィンドウのカーソルプログラムを記述します。
- ペイントで if 条件文を使用したため、このソフト キーボードの最初のキーは使用できず、押した後に更新することもできないため、すべての文字が 1 ビット前に戻ります (代わりにグローバル変数を設定することもできます) if ステートメント) 判断を下すだけです);
- ショートカットを書いた後は実行できません 確認すると g_hSubMenu = GetSubMenu(g_hMenu, 0); return 文の後に文が書かれているため正常に実行できませんが、システムはエラーを報告できません。
3. 実験概要
今回の実験では、授業で先生から教えていただいたウィンドウの知識やメニューの知識を実践するだけでなく、カーソルやアイコンの描画、メニューの作成と使い方、応答方法、ショートカットメニューの読み込みなどを習得しました。また、その使用方法については、インターネット検索やその他の方法を通じて、GetCursorPos()、TrackPopupMenu() などの多くの課外機能についても学びました。独立した思考能力を発揮するだけでなく、視野も広がりました。
附录 关键代码
软键盘绘制代码:
case WM_PAINT:
GetClientRect(hWnd, &rect);
hdc = BeginPaint(hWnd, &ps);
if (!(LOWORD(wParam) == nChildWin_ID))
{
string[n] = number + 65;
n++;
DrawText(hdc, string, n, &rect, DT_SINGLELINE);
}
DrawIcon(hdc,1,1, LoadIcon(hin, MAKEINTRESOURCE(IDI_ICON1)));
EndPaint(hWnd, &ps);
return 0;
子窗口命中写入代码:
case WM_COMMAND:
if (!(LOWORD(wParam) == nChildWin_ID))
{
SendMessage((HWND)hChildWnd[nCol][nRow], WM_CHILDWIN, 0, 0L);
nChildWin_ID = LOWORD(wParam);
nCol = nChildWin_ID >> 4;
nRow = (nChildWin_ID > 15) ? (nChildWin_ID - 4) : nChildWin_ID;
}
else
{
switch (wParam)
{
case ID_CHANGECURSOR:
SetClassLong(hWnd, GCL_HCURSOR,
(LONG)LoadCursor((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDC_CURSOR1)));
break;
}
}
InvalidateRect(hWnd, NULL, TRUE);
return 0;
主窗口绘制菜单,光标,图形代码:
wcMain.hIcon = LoadIcon(hInstance,MAKEINTRESOURCE(IDI_ICON1));
wcMain.hCursor = LoadCursor(hInstance, MAKEINTRESOURCE (IDC_CURSOR2));
wcMain.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wcMain.lpszMenuName = MAKEINTRESOURCE(IDR_MENU3);
改变光标菜单代码:
case WM_COMMAND:
if (!(LOWORD(wParam) == nChildWin_ID))
{
SendMessage((HWND)hChildWnd[nCol][nRow], WM_CHILDWIN, 0, 0L);
nChildWin_ID = LOWORD(wParam);
nCol = nChildWin_ID >> 4;
nRow = (nChildWin_ID > 15) ? (nChildWin_ID - 4) : nChildWin_ID;
}
else
{
switch (wParam)
{
case ID_CHANGECURSOR:
SetClassLong(hWnd, GCL_HCURSOR,
(LONG)LoadCursor((HINSTANCE)GetWindowLong(hWnd, GWL_HINSTANCE),
MAKEINTRESOURCE(IDC_CURSOR1)));
break;
}
}
InvalidateRect(hWnd, NULL, TRUE);
return 0;
右键快捷菜单代码:
case WM_RBUTTONDOWN:
GetCursorPos(&stPos);
TrackPopupMenu(g_hSubMenu,TPM_LEFTALIGN,stPos.x,stPos.y,NULL,hWnd,NULL);
break;