Win32API講座12回
をテンプレートにして作成
[
トップ
] [
新規
|
一覧
|
単語検索
|
最終更新
|
ヘルプ
]
開始行:
今回はウィンドウをクラス化してみます
ウィンドウをクラス化することで
ウィンドウをオブジェクトとして扱えるようになるので
複数のウィンドウを楽に取り扱うことができます
クラス化に関して気を付けなければいけないのはただ一点でウ...
これに関しては後で説明します
今回は3つのファイルを用意します
・WindowClass.h
・WindowClass.cpp
・main.cpp
---------------------------------------------------------...
ウィンドウクラスのヘッダーファイル(WindowClass.h)です
これまでの回で説明した
基本ウィンドウクラスの登録
ウィンドウの作成
初期化、描画、キー、マウス、MCIメッセージ処理を行えるよう...
//---------------------------------------//
// ウィンドウクラス(WindowClass.h)
//
// 作成者:Daiki Terai
// 作成日:2010/11/29
// 修正履歴:
//---------------------------------------//
#ifndef _WINDOWCLASS_H_
#define _WINDOWCLASS_H_
// ウィンドウズバージョン指定
#define _WIN32_WINNT 0x0500
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#pragma comment(lib,"comctl32.lib")
#pragma comment(lib,"winmm.lib")
static const TCHAR* WC_BASIC = _T("Basic"); // 基本ウィ...
// ウィンドウクラス
class CSWindowClass
{
private:
static HINSTANCE m_hInstance; // インスタンスハンドル
HWND m_hWnd; // ウィンドウハンドル
static CSWindowClass* m_pThis; // 登録用
public:
// コンストラクタ
CSWindowClass();
// デストラクタ
virtual ~CSWindowClass();
// 基本ウィンドウクラスの登録
static bool RegistBasicWindowClass();
//-----------------------------------------------------...
// ウィンドウ作成
//
// 引数: Title タイトル
// Width 幅
// Height 高さ
// X X座標
// Y Y座標
// hParentWnd 親ウィンドウハンドル
// hMenu メニューハンドルもしくはリソースID
// ClassName ウィンドウクラス名
// Style ウィンドウスタイル
// ExStyle ウィンドウ拡張スタイル
//
// 戻り値: true: 作成成功
// false: 作成失敗
//-----------------------------------------------------...
virtual bool CreateWnd(
const TCHAR* Title,int Width = CW_USEDEFAULT,int Heigh...
int X = CW_USEDEFAULT,int Y = CW_...
HWND hParentWnd = NULL,HMENU hMen...
const TCHAR* ClassName = WC_BASIC,
DWORD Style = WS_OVERLAPPEDWINDOW...
private:
// ウィンドウプロシージャの管理者
static LRESULT CALLBACK WndProcManager(HWND hWnd,UINT m...
// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wPar...
public:
// メッセージループ
static void MsgLoop(int ArrayLength = 0,CSWindowClass* ...
// メッセージ処理していないときにする処理
virtual void Idle();
// ウィンドウ作成メッセージ
virtual BOOL OnCreate(HWND hWnd,LPCREATESTRUCT lpCreate...
// ウィンドウ破棄メッセージ
virtual void OnDestroy(HWND hWnd);
// ウィンドウ描画メッセージ
virtual void OnPaint(HWND hWnd);
// キー入力関係メッセージ
virtual void OnChar(HWND hWnd, TCHAR ch, int cRepeat);
// マウス関連メッセージ
virtual void OnLButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnRButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnMButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnLButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnRButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnMButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnMouseMove(HWND hwnd, int x, int y, UINT ...
virtual void OnMouseWheel(HWND hWnd, int xPos, int yPos...
};
#endif // _WINDOWCLASS_H_
まずWindowClassのメンバ変数の説明です
private:
static HINSTANCE m_hInstance; // インスタンスハンドル
HWND m_hWnd; // ウィンドウハンドル
static CSWindowClass* m_pThis; // 登録用
m_hInstanceはインスタンスハンドル(アプリケーションのハン...
アプリケーションにつき、ひとつしかないのでstaticとしてお...
m_hWndはウィンドウを作成した際、ウィンドウのハンドルを格...
最後のm_pThisは自クラスのポインタです
これについては何に使うかは実装ファイルで説明します
基本ウィンドウクラス登録メソッド
ウィンドウ作成メソッドと続き
ウィンドウプロシージャを宣言します
ここでウィンドウプロシージャは二つあります
private:
// ウィンドウプロシージャの管理者
static LRESULT CALLBACK WndProcManager(HWND hWnd,UINT m...
// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wPar...
WndProcManagerメンバ関数のほうは、基本ウィンドウクラスの...
静的(static)メンバ関数にしなければ基本ウィンドウクラス...
WndProcメンバ関数はウィンドウ別の本当のプロシージャです
WndProcManagerから適切なウィンドウのプロシージャを呼び出...
ここにウィンドウのクラス化のギミックがあるのですが
詳しい説明は実装ファイルでします
メッセージループの処理もクラス化しました
// メッセージループ
static void MsgLoop(int ArrayLength = 0,CSWindowClass* ...
// メッセージ処理していないときにする処理
virtual void Idle();
Idleに関してはメッセージ処理をしていないときにする処理を...
この講座では説明しませんがこの関数内でDirectXなどの処理を...
メッセージ処理は、このクラスを継承して、以下のメソッドを...
// メッセージ処理していないときにする処理
virtual void Idle();
// ウィンドウ作成メッセージ
virtual BOOL OnCreate(HWND hWnd,LPCREATESTRUCT lpCreate...
// ウィンドウ破棄メッセージ
virtual void OnDestroy(HWND hWnd);
// ウィンドウ描画メッセージ
virtual void OnPaint(HWND hWnd);
// キー入力関係メッセージ
virtual void OnChar(HWND hWnd, TCHAR ch, int cRepeat);
// マウス関連メッセージ
virtual void OnLButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnRButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnMButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnLButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnRButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnMButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnMouseMove(HWND hwnd, int x, int y, UINT ...
virtual void OnMouseWheel(HWND hWnd, int xPos, int yPos...
---------------------------------------------------------...
ウィンドウクラスの実装ファイル(WindowClass.cpp)です
// WindowClass.cpp
#include "WindowClass.h"
// インスタンスハンドル
HINSTANCE CSWindowClass::m_hInstance = NULL;
// 登録用
CSWindowClass* CSWindowClass::m_pThis = NULL;
// コンストラクタ
CSWindowClass::CSWindowClass()
:m_hWnd(NULL)
{
}
// デストラクタ
CSWindowClass::~CSWindowClass(){
}
// シンプルウィンドウクラスの登録
bool CSWindowClass::RegistBasicWindowClass(){
m_hInstance = GetModuleHandle(NULL);
/******************************************************...
/* ウィンドウクラスの定義と作成 */
/******************************************************...
// シンプルウィンドウクラス設定
WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_V...
WndProcManager, 0,0,m_hInstance,
(HICON)LoadImage(NULL,MAKEINTRESOURCE(IDI_APPLICATION),I...
(HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(IDC_ARROW),
IMAGE_CURSOR,0,0,LR_DEFAULTSIZE | LR_SHARED),
(HBRUSH)GetStockObject(WHITE_BRUSH), NULL, WC_BASIC , N...
// シンプルウィンドウクラス作成
if(!RegisterClassEx(&wcex))
return false;
return true;
}
//------------------------------------------------------...
// ウィンドウ作成
//
// 引数: Title タイトル
// Width 幅
// Height 高さ
// X X座標
// Y Y座標
// hParentWnd 親ウィンドウハンドル
// hMenu メニューハンドルもしくはリソースID
// ClassName ウィンドウクラス名
// Style ウィンドウスタイル
// ExStyle ウィンドウ拡張スタイル
//
// 戻り値: true: 作成成功
// false: 作成失敗
//------------------------------------------------------...
bool CSWindowClass::CreateWnd(
const TCHAR* Title,int Width,int Height,int X ,int Y ,
HWND hParentWnd,HMENU hMenu,const TCHAR* ClassName,DWO...
{
// 重要:あとで正しいウィンドウプロシージャを呼び出すた...
m_pThis = this;
/******************************************************...
/* ウィンドウの作成 */
/******************************************************...
m_hWnd = CreateWindowEx(
ExStyle, //拡張ウィンドウスタイル
ClassName, //ウィンドウクラス名
Title, //タイトルバーにこの名前が表示されます
WS_OVERLAPPEDWINDOW | WS_VISIBLE, //ウィンドウスタイル
X, //X座標
Y, //Y座標
Width, //幅
Height, //高さ
hParentWnd, //親ウィンドウのハンドル、親を作るときは...
hMenu, //メニューハンドルorリソースID
m_hInstance, //インスタンスハンドル
NULL);
// ウィンドウ作成失敗
if (m_hWnd == NULL)
return false;
return true;
}
//-----------------------------------------------------//
// ウィンドウプロシージャの管理者
// 基本ウィンドウクラスではこの関数を登録して
// この関数を経由して各ウィンドウの本当のプロシージャを...
//
// 引数: hWnd ウィンドウハンドル
// msg メッセージ
// wParam パラメータ
// lParam パラメータ
//
// 戻り値:処理結果
//-----------------------------------------------------//
LRESULT CALLBACK CSWindowClass::WndProcManager(HWND hWnd...
CSWindowClass* pWindow = (CSWindowClass*)(LONG_PTR)GetW...
//thisポインタが取得できた場合
if( pWindow != NULL)
{
// 本当のウィンドウプロシージャを呼び出しメッセージ処...
LRESULT lResult = pWindow->WndProc( hWnd, msg, wParam,...
return lResult;
}
//thisポインタが取得できなかった場合
else
{
// ウィンドウの作成時の場合
if( msg == WM_CREATE || msg == WM_INITDIALOG){
// プロパティリストにオブジェクトポインタ(thisポイン...
SetWindowLongPtr( hWnd, GWL_USERDATA, (LONG)(LONG_PTR...
// 初期化メッセージの再送信
SendMessage(hWnd,msg,wParam,lParam);
m_pThis = NULL; // 登録したので一時インスタンスポイン...
}
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
//-----------------------------------------------------//
// ウィンドウプロシージャ
// デフォルトの処理はDefWindowProc関数で行う
//
// 引数: hWnd ウィンドウハンドル
// msg メッセージ
// wParam パラメータ
// lParam パラメータ
//
// 戻り値:処理結果
//-----------------------------------------------------//
LRESULT CALLBACK CSWindowClass::WndProc(HWND hWnd, UINT ...
switch(msg){
HANDLE_MSG(hWnd,WM_CREATE,OnCreate);
HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy);
HANDLE_MSG(hWnd,WM_PAINT,OnPaint);
// キーボード
HANDLE_MSG(hWnd,WM_CHAR,OnChar);
// マウス
HANDLE_MSG(hWnd,WM_LBUTTONDOWN,OnLButtonDown);
HANDLE_MSG(hWnd,WM_RBUTTONDOWN,OnRButtonDown);
HANDLE_MSG(hWnd,WM_MBUTTONDOWN,OnMButtonDown);
HANDLE_MSG(hWnd,WM_LBUTTONDBLCLK,OnLButtonDown);
HANDLE_MSG(hWnd,WM_RBUTTONDBLCLK,OnRButtonDown);
HANDLE_MSG(hWnd,WM_LBUTTONUP,OnLButtonUp);
HANDLE_MSG(hWnd,WM_RBUTTONUP,OnRButtonUp);
HANDLE_MSG(hWnd,WM_MBUTTONUP,OnMButtonUp);
HANDLE_MSG(hWnd,WM_MOUSEMOVE,OnMouseMove);
HANDLE_MSG(hWnd,WM_MOUSEWHEEL,OnMouseWheel);
// MCI処理終了通知メッセージ
case MM_MCINOTIFY:{
MCI_PLAY_PARMS mciPlay;
// 通知メッセージ失敗
if (wParam != MCI_NOTIFY_SUCCESSFUL)
return 0;
// 初期位置に戻す
mciSendCommand((MCIDEVICEID)lParam, MCI_SEEK, MCI_SEE...
mciPlay.dwCallback = (DWORD_PTR)hWnd;
// ループ再生
mciSendCommand((MCIDEVICEID)lParam, MCI_PLAY, MCI_NOT...
return 0;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
// メッセージループ
void CSWindowClass::MsgLoop(int ArrayLength,CSWindowClas...
/******************************************************...
/* メッセージループ */
/******************************************************...
MSG msg = {};
while(msg.message != WM_QUIT) {
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
// メッセージ処理をしてないときする処理
for(int i = 0;i < ArrayLength;++i){
pWindowArray[i].Idle();
}
}
}
}
// メッセージ処理していないときにする処理
void CSWindowClass::Idle(){
// 継承時に処理を書く
}
// ウィンドウ作成メッセージ
BOOL CSWindowClass::OnCreate(HWND hWnd,LPCREATESTRUCT lp...
return TRUE;
}
// ウィンドウ破棄メッセージ
void CSWindowClass::OnDestroy(HWND hWnd){
PostQuitMessage(0);
}
// ウィンドウ描画メッセージ
void CSWindowClass::OnPaint(HWND hWnd){
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
EndPaint(hWnd,&ps);
}
// キー入力メッセージ
void CSWindowClass::OnChar(HWND hWnd, TCHAR ch, int cRep...
// マウス左ボタン押下メッセージ
void CSWindowClass::OnLButtonDown(HWND hWnd, BOOL isDoub...
// マウス右ボタン押下メッセージ
void CSWindowClass::OnRButtonDown(HWND hWnd, BOOL isDoub...
// マウス真ん中ボタン押下メッセージ
void CSWindowClass::OnMButtonDown(HWND hWnd, BOOL isDoub...
// マウス左ボタン押上メッセージ
void CSWindowClass::OnLButtonUp(HWND hWnd,int x, int y, ...
// マウス右ボタン押上げメッセージ
void CSWindowClass::OnRButtonUp(HWND hWnd,int x, int y, ...
// マウス真ん中ボタン押上メッセージ
void CSWindowClass::OnMButtonUp(HWND hWnd,int x, int y, ...
// マウス移動メッセージ
void CSWindowClass::OnMouseMove(HWND hwnd, int x, int y,...
// マウスホイールメッセージ
void CSWindowClass::OnMouseWheel(HWND hWnd, int xPos, in...
ほとんどは今までの回でやったことをそのまま実装しただけです
ただし、クラス化する上でいくつか注意しなければならない点...
まず、基本ウィンドウクラスの登録用の設定です
// 基本ウィンドウクラス設定
WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VR...
WndProcManager,
0,0,m_hInstance,
(HICON)LoadImage(NULL,MAKEINTRESOURCE(IDI_APPLICATION),I...
(HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(IDC_ARROW),IMAGE...
(HBRUSH)GetStockObject(WHITE_BRUSH), NULL, WC_BASIC , NU...
静的メンバ関数のWndProcManager関数ポインタを指定しています
グローバルな関数ポインタあるいは静的なメンバ関数ポインタ...
なので、ウィンドウ別のウィンドウプロシージャはWndProcMana...
これを実現するために
CreateWndメンバ関数の実装でまず、オブジェクト自分自身のポ...
これは、インスタンス化されたオブジェクトと同じポインタと...
// 重要:あとで正しいウィンドウプロシージャを呼び...
m_pThis = this;
このあとCreateWindowEx関数を呼び出します
/******************************************************...
/* ウィンドウの作成 */
/******************************************************...
m_hWnd = CreateWindowEx(
ExStyle, //拡張ウィンドウスタイル
ClassName, //ウィンドウクラス名
Title, //タイトルバーにこの名前が表示されます
WS_OVERLAPPEDWINDOW | WS_VISIBLE, //ウィンドウスタイル
X, //X座標
Y, //Y座標
Width, //幅
Height, //高さ
hParentWnd, //親ウィンドウのハンドル、親を作るときは...
hMenu, //メニューハンドルorリソースID
m_hInstance, //インスタンスハンドル
NULL);
CreateWindowEx関数は基本ウィンドウクラスの
指定されたウィンドウプロシージャ(WndProcManager)へWM_CREA...
//-----------------------------------------------------//
// ウィンドウプロシージャの管理者
// 基本ウィンドウクラスではこの関数を登録して
// この関数を経由して各ウィンドウの本当のプロシージャを...
//
// 引数: hWnd ウィンドウハンドル
// msg メッセージ
// wParam パラメータ
// lParam パラメータ
//
// 戻り値:処理結果
//-----------------------------------------------------//
LRESULT CALLBACK CSWindowClass::WndProcManager(HWND hWnd...
CSWindowClass* pWindow = (CSWindowClass*)(LONG_PTR)GetW...
//thisポインタが取得できた場合
if( pWindow != NULL)
{
// 本当のウィンドウプロシージャを呼び出しメッセージ処...
LRESULT lResult = pWindow->WndProc( hWnd, msg, wParam,...
return lResult;
}
//thisポインタが取得できなかった場合
else
{
// ウィンドウの作成時の場合
if( msg == WM_CREATE || msg == WM_INITDIALOG){
// プロパティリストにオブジェクトポインタ(thisポイン...
SetWindowLongPtr( hWnd, GWL_USERDATA, (LONG)(LONG_PTR...
// 初期化メッセージの再送信
SendMessage(hWnd,msg,wParam,lParam);
m_pThis = NULL; // 登録したので一時インスタンスポイン...
}
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
まずいきなりGetWindowLong関数というものが出てきました
CSWindowClass* pWindow = (CSWindowClass*)(LONG_PTR)GetWi...
GetWindowLong関数の第二引数にGWL_USERDATAを指定すると
第一引数のウィンドウに関連付けられたデータを取得できます
何もデータがない場合は0が入っています
(この関数は他にも用途が色々あるのですが、それはまた今度...
WM_CREATEが送られてきたウィンドウにはまだ何もデータを入れ...
//thisポインタが取得できなかった場合
else
{
// ウィンドウの作成時の場合
if( msg == WM_CREATE || msg == WM_INITDIALOG){
// プロパティリストにオブジェクトポインタ(thisポイン...
SetWindowLongPtr( hWnd, GWL_USERDATA, (LONG)(LONG_PTR...
// 初期化メッセージの再送信
SendMessage(hWnd,msg,wParam,lParam);
m_pThis = NULL; // 登録したので一時インスタンスポイン...
}
}
WM_INITDIALOGメッセージについてはまだ説明していませんでし...
ダイアログの作成時にはWM_CREATEの代わりにWM_INITDIALOGが...
(詳しくはダイアログの回に説明します)
今回の肝はここです
// プロパティリストにオブジェクトポインタ(thisポインタ)...
SetWindowLongPtr( hWnd, GWL_USERDATA, (LONG)(LONG_PTR)(m...
SetWindowLongPtr関数でウィンドウハンドルと対応のあるウィ...
そして、WM_CREATEメッセージまたはWM_INITDIALOGメッセージ...
// 初期化メッセージの再送信
SendMessage(hWnd,msg,wParam,lParam);
メッセージの送信にはSendMessage関数を使います
LRESULT SendMessage(
HWND hWnd, // 送信先ウィンドウのハンドル
UINT Msg, // メッセージ
WPARAM wParam, // メッセージの最初のパラメータ
LPARAM lParam // メッセージの 2 番目のパラメータ
);
SendMessage関数は単純にメッセージ送るだけでなく,コントロ...
さて、WndProcManagerに再びメッセージが送られることになる...
CSWindowClass* pWindow = (CSWindowClass*)(LONG_PTR)GetWi...
これ以降は、ウィンドウハンドルに対応付けられたウィンドウ...
メンバ関数化されたウィンドウプロシージャを呼び出すには
GetWindowLong関数で取得したウィンドウオブジェクトのポイン...
//thisポインタが取得できた場合
if( pWindow != NULL)
{
// 本当のウィンドウプロシージャを呼び出しメッセージ処理...
LRESULT lResult = pWindow->WndProc( hWnd, msg, wParam, ...
return lResult;
}
なぜ、これだけ回りくどいことをしているのでしょうか?
これではいけないのでしょうか?
LRESULT CALLBACK CSWindowClass::WndProcManager(HWND hWnd...
// 本当のウィンドウプロシージャを呼び出しメッセージ処理...
return WndProc( hWnd, msg, wParam, lParam);
}
実は静的(static)なメンバ関数では通常のメンバ関数やメンバ...
(静的なメンバ関数や静的なメンバ変数はOK)
なので一度、ウィンドウデータ空間にウィンドウオブジェクト...
そのウィンドウに対応する本当のウィンドウプロシージャを呼...
---------------------------------------------------------...
メインコード(main.cpp)です
ウィンドウをクラス化したことによりすっきりしました
#include "WindowClass.h"
// コンソール画面隠蔽
#pragma comment(linker, "/subsystem:\"windows\" /entry:\...
int main(int argc,char* argv[])
{
// 基本ウィンドウクラス登録
CSWindowClass::RegistBasicWindowClass();
// 基本ウィンドウ作成
CSWindowClass Window;
Window.CreateWnd(_T("タイトル"));
// メッセージループ
CSWindowClass::MsgLoop();
return 0;
}
今回のソースファイルは下からダウンロードできます
&ref(WindowClass.zip);
|(^ω^)やったお|11|
|何これwww意味不すぎwww|2|
|。(`ω´#)。あぁん?最近、だらしねぇな|1|
終了行:
今回はウィンドウをクラス化してみます
ウィンドウをクラス化することで
ウィンドウをオブジェクトとして扱えるようになるので
複数のウィンドウを楽に取り扱うことができます
クラス化に関して気を付けなければいけないのはただ一点でウ...
これに関しては後で説明します
今回は3つのファイルを用意します
・WindowClass.h
・WindowClass.cpp
・main.cpp
---------------------------------------------------------...
ウィンドウクラスのヘッダーファイル(WindowClass.h)です
これまでの回で説明した
基本ウィンドウクラスの登録
ウィンドウの作成
初期化、描画、キー、マウス、MCIメッセージ処理を行えるよう...
//---------------------------------------//
// ウィンドウクラス(WindowClass.h)
//
// 作成者:Daiki Terai
// 作成日:2010/11/29
// 修正履歴:
//---------------------------------------//
#ifndef _WINDOWCLASS_H_
#define _WINDOWCLASS_H_
// ウィンドウズバージョン指定
#define _WIN32_WINNT 0x0500
#include <tchar.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <windowsx.h>
#include <commctrl.h>
#pragma comment(lib,"comctl32.lib")
#pragma comment(lib,"winmm.lib")
static const TCHAR* WC_BASIC = _T("Basic"); // 基本ウィ...
// ウィンドウクラス
class CSWindowClass
{
private:
static HINSTANCE m_hInstance; // インスタンスハンドル
HWND m_hWnd; // ウィンドウハンドル
static CSWindowClass* m_pThis; // 登録用
public:
// コンストラクタ
CSWindowClass();
// デストラクタ
virtual ~CSWindowClass();
// 基本ウィンドウクラスの登録
static bool RegistBasicWindowClass();
//-----------------------------------------------------...
// ウィンドウ作成
//
// 引数: Title タイトル
// Width 幅
// Height 高さ
// X X座標
// Y Y座標
// hParentWnd 親ウィンドウハンドル
// hMenu メニューハンドルもしくはリソースID
// ClassName ウィンドウクラス名
// Style ウィンドウスタイル
// ExStyle ウィンドウ拡張スタイル
//
// 戻り値: true: 作成成功
// false: 作成失敗
//-----------------------------------------------------...
virtual bool CreateWnd(
const TCHAR* Title,int Width = CW_USEDEFAULT,int Heigh...
int X = CW_USEDEFAULT,int Y = CW_...
HWND hParentWnd = NULL,HMENU hMen...
const TCHAR* ClassName = WC_BASIC,
DWORD Style = WS_OVERLAPPEDWINDOW...
private:
// ウィンドウプロシージャの管理者
static LRESULT CALLBACK WndProcManager(HWND hWnd,UINT m...
// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wPar...
public:
// メッセージループ
static void MsgLoop(int ArrayLength = 0,CSWindowClass* ...
// メッセージ処理していないときにする処理
virtual void Idle();
// ウィンドウ作成メッセージ
virtual BOOL OnCreate(HWND hWnd,LPCREATESTRUCT lpCreate...
// ウィンドウ破棄メッセージ
virtual void OnDestroy(HWND hWnd);
// ウィンドウ描画メッセージ
virtual void OnPaint(HWND hWnd);
// キー入力関係メッセージ
virtual void OnChar(HWND hWnd, TCHAR ch, int cRepeat);
// マウス関連メッセージ
virtual void OnLButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnRButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnMButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnLButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnRButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnMButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnMouseMove(HWND hwnd, int x, int y, UINT ...
virtual void OnMouseWheel(HWND hWnd, int xPos, int yPos...
};
#endif // _WINDOWCLASS_H_
まずWindowClassのメンバ変数の説明です
private:
static HINSTANCE m_hInstance; // インスタンスハンドル
HWND m_hWnd; // ウィンドウハンドル
static CSWindowClass* m_pThis; // 登録用
m_hInstanceはインスタンスハンドル(アプリケーションのハン...
アプリケーションにつき、ひとつしかないのでstaticとしてお...
m_hWndはウィンドウを作成した際、ウィンドウのハンドルを格...
最後のm_pThisは自クラスのポインタです
これについては何に使うかは実装ファイルで説明します
基本ウィンドウクラス登録メソッド
ウィンドウ作成メソッドと続き
ウィンドウプロシージャを宣言します
ここでウィンドウプロシージャは二つあります
private:
// ウィンドウプロシージャの管理者
static LRESULT CALLBACK WndProcManager(HWND hWnd,UINT m...
// ウィンドウプロシージャ
LRESULT CALLBACK WndProc(HWND hWnd,UINT msg,WPARAM wPar...
WndProcManagerメンバ関数のほうは、基本ウィンドウクラスの...
静的(static)メンバ関数にしなければ基本ウィンドウクラス...
WndProcメンバ関数はウィンドウ別の本当のプロシージャです
WndProcManagerから適切なウィンドウのプロシージャを呼び出...
ここにウィンドウのクラス化のギミックがあるのですが
詳しい説明は実装ファイルでします
メッセージループの処理もクラス化しました
// メッセージループ
static void MsgLoop(int ArrayLength = 0,CSWindowClass* ...
// メッセージ処理していないときにする処理
virtual void Idle();
Idleに関してはメッセージ処理をしていないときにする処理を...
この講座では説明しませんがこの関数内でDirectXなどの処理を...
メッセージ処理は、このクラスを継承して、以下のメソッドを...
// メッセージ処理していないときにする処理
virtual void Idle();
// ウィンドウ作成メッセージ
virtual BOOL OnCreate(HWND hWnd,LPCREATESTRUCT lpCreate...
// ウィンドウ破棄メッセージ
virtual void OnDestroy(HWND hWnd);
// ウィンドウ描画メッセージ
virtual void OnPaint(HWND hWnd);
// キー入力関係メッセージ
virtual void OnChar(HWND hWnd, TCHAR ch, int cRepeat);
// マウス関連メッセージ
virtual void OnLButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnRButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnMButtonDown(HWND hWnd, BOOL isDoubleClic...
virtual void OnLButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnRButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnMButtonUp(HWND hWnd,int x, int y, UINT k...
virtual void OnMouseMove(HWND hwnd, int x, int y, UINT ...
virtual void OnMouseWheel(HWND hWnd, int xPos, int yPos...
---------------------------------------------------------...
ウィンドウクラスの実装ファイル(WindowClass.cpp)です
// WindowClass.cpp
#include "WindowClass.h"
// インスタンスハンドル
HINSTANCE CSWindowClass::m_hInstance = NULL;
// 登録用
CSWindowClass* CSWindowClass::m_pThis = NULL;
// コンストラクタ
CSWindowClass::CSWindowClass()
:m_hWnd(NULL)
{
}
// デストラクタ
CSWindowClass::~CSWindowClass(){
}
// シンプルウィンドウクラスの登録
bool CSWindowClass::RegistBasicWindowClass(){
m_hInstance = GetModuleHandle(NULL);
/******************************************************...
/* ウィンドウクラスの定義と作成 */
/******************************************************...
// シンプルウィンドウクラス設定
WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_V...
WndProcManager, 0,0,m_hInstance,
(HICON)LoadImage(NULL,MAKEINTRESOURCE(IDI_APPLICATION),I...
(HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(IDC_ARROW),
IMAGE_CURSOR,0,0,LR_DEFAULTSIZE | LR_SHARED),
(HBRUSH)GetStockObject(WHITE_BRUSH), NULL, WC_BASIC , N...
// シンプルウィンドウクラス作成
if(!RegisterClassEx(&wcex))
return false;
return true;
}
//------------------------------------------------------...
// ウィンドウ作成
//
// 引数: Title タイトル
// Width 幅
// Height 高さ
// X X座標
// Y Y座標
// hParentWnd 親ウィンドウハンドル
// hMenu メニューハンドルもしくはリソースID
// ClassName ウィンドウクラス名
// Style ウィンドウスタイル
// ExStyle ウィンドウ拡張スタイル
//
// 戻り値: true: 作成成功
// false: 作成失敗
//------------------------------------------------------...
bool CSWindowClass::CreateWnd(
const TCHAR* Title,int Width,int Height,int X ,int Y ,
HWND hParentWnd,HMENU hMenu,const TCHAR* ClassName,DWO...
{
// 重要:あとで正しいウィンドウプロシージャを呼び出すた...
m_pThis = this;
/******************************************************...
/* ウィンドウの作成 */
/******************************************************...
m_hWnd = CreateWindowEx(
ExStyle, //拡張ウィンドウスタイル
ClassName, //ウィンドウクラス名
Title, //タイトルバーにこの名前が表示されます
WS_OVERLAPPEDWINDOW | WS_VISIBLE, //ウィンドウスタイル
X, //X座標
Y, //Y座標
Width, //幅
Height, //高さ
hParentWnd, //親ウィンドウのハンドル、親を作るときは...
hMenu, //メニューハンドルorリソースID
m_hInstance, //インスタンスハンドル
NULL);
// ウィンドウ作成失敗
if (m_hWnd == NULL)
return false;
return true;
}
//-----------------------------------------------------//
// ウィンドウプロシージャの管理者
// 基本ウィンドウクラスではこの関数を登録して
// この関数を経由して各ウィンドウの本当のプロシージャを...
//
// 引数: hWnd ウィンドウハンドル
// msg メッセージ
// wParam パラメータ
// lParam パラメータ
//
// 戻り値:処理結果
//-----------------------------------------------------//
LRESULT CALLBACK CSWindowClass::WndProcManager(HWND hWnd...
CSWindowClass* pWindow = (CSWindowClass*)(LONG_PTR)GetW...
//thisポインタが取得できた場合
if( pWindow != NULL)
{
// 本当のウィンドウプロシージャを呼び出しメッセージ処...
LRESULT lResult = pWindow->WndProc( hWnd, msg, wParam,...
return lResult;
}
//thisポインタが取得できなかった場合
else
{
// ウィンドウの作成時の場合
if( msg == WM_CREATE || msg == WM_INITDIALOG){
// プロパティリストにオブジェクトポインタ(thisポイン...
SetWindowLongPtr( hWnd, GWL_USERDATA, (LONG)(LONG_PTR...
// 初期化メッセージの再送信
SendMessage(hWnd,msg,wParam,lParam);
m_pThis = NULL; // 登録したので一時インスタンスポイン...
}
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
//-----------------------------------------------------//
// ウィンドウプロシージャ
// デフォルトの処理はDefWindowProc関数で行う
//
// 引数: hWnd ウィンドウハンドル
// msg メッセージ
// wParam パラメータ
// lParam パラメータ
//
// 戻り値:処理結果
//-----------------------------------------------------//
LRESULT CALLBACK CSWindowClass::WndProc(HWND hWnd, UINT ...
switch(msg){
HANDLE_MSG(hWnd,WM_CREATE,OnCreate);
HANDLE_MSG(hWnd,WM_DESTROY,OnDestroy);
HANDLE_MSG(hWnd,WM_PAINT,OnPaint);
// キーボード
HANDLE_MSG(hWnd,WM_CHAR,OnChar);
// マウス
HANDLE_MSG(hWnd,WM_LBUTTONDOWN,OnLButtonDown);
HANDLE_MSG(hWnd,WM_RBUTTONDOWN,OnRButtonDown);
HANDLE_MSG(hWnd,WM_MBUTTONDOWN,OnMButtonDown);
HANDLE_MSG(hWnd,WM_LBUTTONDBLCLK,OnLButtonDown);
HANDLE_MSG(hWnd,WM_RBUTTONDBLCLK,OnRButtonDown);
HANDLE_MSG(hWnd,WM_LBUTTONUP,OnLButtonUp);
HANDLE_MSG(hWnd,WM_RBUTTONUP,OnRButtonUp);
HANDLE_MSG(hWnd,WM_MBUTTONUP,OnMButtonUp);
HANDLE_MSG(hWnd,WM_MOUSEMOVE,OnMouseMove);
HANDLE_MSG(hWnd,WM_MOUSEWHEEL,OnMouseWheel);
// MCI処理終了通知メッセージ
case MM_MCINOTIFY:{
MCI_PLAY_PARMS mciPlay;
// 通知メッセージ失敗
if (wParam != MCI_NOTIFY_SUCCESSFUL)
return 0;
// 初期位置に戻す
mciSendCommand((MCIDEVICEID)lParam, MCI_SEEK, MCI_SEE...
mciPlay.dwCallback = (DWORD_PTR)hWnd;
// ループ再生
mciSendCommand((MCIDEVICEID)lParam, MCI_PLAY, MCI_NOT...
return 0;
}
}
return DefWindowProc(hWnd, msg, wParam, lParam);
}
// メッセージループ
void CSWindowClass::MsgLoop(int ArrayLength,CSWindowClas...
/******************************************************...
/* メッセージループ */
/******************************************************...
MSG msg = {};
while(msg.message != WM_QUIT) {
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else{
// メッセージ処理をしてないときする処理
for(int i = 0;i < ArrayLength;++i){
pWindowArray[i].Idle();
}
}
}
}
// メッセージ処理していないときにする処理
void CSWindowClass::Idle(){
// 継承時に処理を書く
}
// ウィンドウ作成メッセージ
BOOL CSWindowClass::OnCreate(HWND hWnd,LPCREATESTRUCT lp...
return TRUE;
}
// ウィンドウ破棄メッセージ
void CSWindowClass::OnDestroy(HWND hWnd){
PostQuitMessage(0);
}
// ウィンドウ描画メッセージ
void CSWindowClass::OnPaint(HWND hWnd){
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd,&ps);
EndPaint(hWnd,&ps);
}
// キー入力メッセージ
void CSWindowClass::OnChar(HWND hWnd, TCHAR ch, int cRep...
// マウス左ボタン押下メッセージ
void CSWindowClass::OnLButtonDown(HWND hWnd, BOOL isDoub...
// マウス右ボタン押下メッセージ
void CSWindowClass::OnRButtonDown(HWND hWnd, BOOL isDoub...
// マウス真ん中ボタン押下メッセージ
void CSWindowClass::OnMButtonDown(HWND hWnd, BOOL isDoub...
// マウス左ボタン押上メッセージ
void CSWindowClass::OnLButtonUp(HWND hWnd,int x, int y, ...
// マウス右ボタン押上げメッセージ
void CSWindowClass::OnRButtonUp(HWND hWnd,int x, int y, ...
// マウス真ん中ボタン押上メッセージ
void CSWindowClass::OnMButtonUp(HWND hWnd,int x, int y, ...
// マウス移動メッセージ
void CSWindowClass::OnMouseMove(HWND hwnd, int x, int y,...
// マウスホイールメッセージ
void CSWindowClass::OnMouseWheel(HWND hWnd, int xPos, in...
ほとんどは今までの回でやったことをそのまま実装しただけです
ただし、クラス化する上でいくつか注意しなければならない点...
まず、基本ウィンドウクラスの登録用の設定です
// 基本ウィンドウクラス設定
WNDCLASSEX wcex ={sizeof(WNDCLASSEX), CS_HREDRAW | CS_VR...
WndProcManager,
0,0,m_hInstance,
(HICON)LoadImage(NULL,MAKEINTRESOURCE(IDI_APPLICATION),I...
(HCURSOR)LoadImage(NULL,MAKEINTRESOURCE(IDC_ARROW),IMAGE...
(HBRUSH)GetStockObject(WHITE_BRUSH), NULL, WC_BASIC , NU...
静的メンバ関数のWndProcManager関数ポインタを指定しています
グローバルな関数ポインタあるいは静的なメンバ関数ポインタ...
なので、ウィンドウ別のウィンドウプロシージャはWndProcMana...
これを実現するために
CreateWndメンバ関数の実装でまず、オブジェクト自分自身のポ...
これは、インスタンス化されたオブジェクトと同じポインタと...
// 重要:あとで正しいウィンドウプロシージャを呼び...
m_pThis = this;
このあとCreateWindowEx関数を呼び出します
/******************************************************...
/* ウィンドウの作成 */
/******************************************************...
m_hWnd = CreateWindowEx(
ExStyle, //拡張ウィンドウスタイル
ClassName, //ウィンドウクラス名
Title, //タイトルバーにこの名前が表示されます
WS_OVERLAPPEDWINDOW | WS_VISIBLE, //ウィンドウスタイル
X, //X座標
Y, //Y座標
Width, //幅
Height, //高さ
hParentWnd, //親ウィンドウのハンドル、親を作るときは...
hMenu, //メニューハンドルorリソースID
m_hInstance, //インスタンスハンドル
NULL);
CreateWindowEx関数は基本ウィンドウクラスの
指定されたウィンドウプロシージャ(WndProcManager)へWM_CREA...
//-----------------------------------------------------//
// ウィンドウプロシージャの管理者
// 基本ウィンドウクラスではこの関数を登録して
// この関数を経由して各ウィンドウの本当のプロシージャを...
//
// 引数: hWnd ウィンドウハンドル
// msg メッセージ
// wParam パラメータ
// lParam パラメータ
//
// 戻り値:処理結果
//-----------------------------------------------------//
LRESULT CALLBACK CSWindowClass::WndProcManager(HWND hWnd...
CSWindowClass* pWindow = (CSWindowClass*)(LONG_PTR)GetW...
//thisポインタが取得できた場合
if( pWindow != NULL)
{
// 本当のウィンドウプロシージャを呼び出しメッセージ処...
LRESULT lResult = pWindow->WndProc( hWnd, msg, wParam,...
return lResult;
}
//thisポインタが取得できなかった場合
else
{
// ウィンドウの作成時の場合
if( msg == WM_CREATE || msg == WM_INITDIALOG){
// プロパティリストにオブジェクトポインタ(thisポイン...
SetWindowLongPtr( hWnd, GWL_USERDATA, (LONG)(LONG_PTR...
// 初期化メッセージの再送信
SendMessage(hWnd,msg,wParam,lParam);
m_pThis = NULL; // 登録したので一時インスタンスポイン...
}
}
return DefWindowProc(hWnd,msg,wParam,lParam);
}
まずいきなりGetWindowLong関数というものが出てきました
CSWindowClass* pWindow = (CSWindowClass*)(LONG_PTR)GetWi...
GetWindowLong関数の第二引数にGWL_USERDATAを指定すると
第一引数のウィンドウに関連付けられたデータを取得できます
何もデータがない場合は0が入っています
(この関数は他にも用途が色々あるのですが、それはまた今度...
WM_CREATEが送られてきたウィンドウにはまだ何もデータを入れ...
//thisポインタが取得できなかった場合
else
{
// ウィンドウの作成時の場合
if( msg == WM_CREATE || msg == WM_INITDIALOG){
// プロパティリストにオブジェクトポインタ(thisポイン...
SetWindowLongPtr( hWnd, GWL_USERDATA, (LONG)(LONG_PTR...
// 初期化メッセージの再送信
SendMessage(hWnd,msg,wParam,lParam);
m_pThis = NULL; // 登録したので一時インスタンスポイン...
}
}
WM_INITDIALOGメッセージについてはまだ説明していませんでし...
ダイアログの作成時にはWM_CREATEの代わりにWM_INITDIALOGが...
(詳しくはダイアログの回に説明します)
今回の肝はここです
// プロパティリストにオブジェクトポインタ(thisポインタ)...
SetWindowLongPtr( hWnd, GWL_USERDATA, (LONG)(LONG_PTR)(m...
SetWindowLongPtr関数でウィンドウハンドルと対応のあるウィ...
そして、WM_CREATEメッセージまたはWM_INITDIALOGメッセージ...
// 初期化メッセージの再送信
SendMessage(hWnd,msg,wParam,lParam);
メッセージの送信にはSendMessage関数を使います
LRESULT SendMessage(
HWND hWnd, // 送信先ウィンドウのハンドル
UINT Msg, // メッセージ
WPARAM wParam, // メッセージの最初のパラメータ
LPARAM lParam // メッセージの 2 番目のパラメータ
);
SendMessage関数は単純にメッセージ送るだけでなく,コントロ...
さて、WndProcManagerに再びメッセージが送られることになる...
CSWindowClass* pWindow = (CSWindowClass*)(LONG_PTR)GetWi...
これ以降は、ウィンドウハンドルに対応付けられたウィンドウ...
メンバ関数化されたウィンドウプロシージャを呼び出すには
GetWindowLong関数で取得したウィンドウオブジェクトのポイン...
//thisポインタが取得できた場合
if( pWindow != NULL)
{
// 本当のウィンドウプロシージャを呼び出しメッセージ処理...
LRESULT lResult = pWindow->WndProc( hWnd, msg, wParam, ...
return lResult;
}
なぜ、これだけ回りくどいことをしているのでしょうか?
これではいけないのでしょうか?
LRESULT CALLBACK CSWindowClass::WndProcManager(HWND hWnd...
// 本当のウィンドウプロシージャを呼び出しメッセージ処理...
return WndProc( hWnd, msg, wParam, lParam);
}
実は静的(static)なメンバ関数では通常のメンバ関数やメンバ...
(静的なメンバ関数や静的なメンバ変数はOK)
なので一度、ウィンドウデータ空間にウィンドウオブジェクト...
そのウィンドウに対応する本当のウィンドウプロシージャを呼...
---------------------------------------------------------...
メインコード(main.cpp)です
ウィンドウをクラス化したことによりすっきりしました
#include "WindowClass.h"
// コンソール画面隠蔽
#pragma comment(linker, "/subsystem:\"windows\" /entry:\...
int main(int argc,char* argv[])
{
// 基本ウィンドウクラス登録
CSWindowClass::RegistBasicWindowClass();
// 基本ウィンドウ作成
CSWindowClass Window;
Window.CreateWnd(_T("タイトル"));
// メッセージループ
CSWindowClass::MsgLoop();
return 0;
}
今回のソースファイルは下からダウンロードできます
&ref(WindowClass.zip);
|(^ω^)やったお|11|
|何これwww意味不すぎwww|2|
|。(`ω´#)。あぁん?最近、だらしねぇな|1|
ページ名: