VC++2008のWindowsフォームアプリケーションで
WindowsAPIのウインドウを作って使いたいのですが、この場合どのようにすれば
普通にフォームアプリケーションに新しい子ウインドウを表示させる
Form^ a;
a->Show();
のように
メッセージループ(?)をさせる事が出来るのでしょうか?
WindowsAPIの解説サイトや本などを見ても、大抵はそれのみの解説のため、while文で自身に対してそうするだけでいいようなのですが
同じようにフォームアプリケーションの子ウインドウとしてやろうとすると、そうするだけでは当然メインフォーム側の操作が出来なくなってしまいます。
どのように実現したらいいのでしょうか?
また、そもそも上記のように普通に子ウインドウを作った場合は、どのように実現されているのでしょうか?
No.1
- 回答日時:
API関数CreateWindowExでウィンドゥを作成すれば、OSが勝手にメッセージループを呼び出します。
もちろん、デフォルトのメッセージループは標準の事だけしかせず、何もしてくれないので、メッセージループをフックして、それなりの事を書いてあげないとなりません。
親は「どっかに勝手に動いてる子が居る」って事だけを意識していれば良いです(終了時に後始末、とか)
なるほど、ありがとうございます!
ということは、実行中は、これが来たらこうするというのを書けばいいだけ、という事ですか。
ではその・・・具体的な処理内容は、この場合だとどこにどういう風に書けばいいのでしょうか?
かなりの概要的な言い方をすると
ウインドウ用のクラスを別途作っておいて
そのインスタンスを、親となるフォームの中に作っておく、という事で実現できるのでしょうか・・・?
No.2
- 回答日時:
こんにちは。
>>そもそも上記のように普通に子ウインドウを作った場合は、どのように実現されているのでしょうか?
ウィンドウプロシージャーという関数に対し、メッセージコールバックが掛かる様になっています。
//CreateWindowで広げたウィンドウが、何かされる度、ココに飛び込んでくる
LRESULT CALLBACK Win32ChildProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)//ココでメッセージを引っ掛ける
{
case WM_KEYDOWN:
{
//例えばキーが押された
}
}
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
//Form1のコンストラクタで開いてみる
public: Form1(void)
{
InitializeComponent();
//
//TODO: ここにコンストラクタ コードを追加します
//
//白い子ウィンドウ(キャプション無し)を作成する
HWND hWnd = this->OpenChildWindow();
//ウィンドウを表示する
::ShowWindow(hWnd, SW_SHOW);
}
//win32でウィンドウを開くメソッド
private:HWND OpenChildWindow()
{
HINSTANCE hInst= ::GetModuleHandle(NULL);
WNDCLASSEX wc = {sizeof(wc)};
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = &::Win32ChildProc;
wc.hInstance = hInst;
wc.hCursor = LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW+1);
wc.lpszClassName = L"test c++cli win32";
if(!::RegisterClassEx(&wc))return NULL;
return ::CreateWindowEx(WS_EX_CLIENTEDGE,
wc.lpszClassName,
L"hello win32",
WS_CHILD | WS_VISIBLE,
0, 0, this->Width, this->Height, static_cast<HWND>(this->Handle.ToPointer()), NULL, hInst, NULL);
}
こんにちは。
おおお!ありがとうございます!
とりあえず、メンバとして用意しコンストラクタでwin32でウィンドウを開くメソッドを呼び出し
ウインドウを開くのは出来ました!
でも残りの一歩が分かりません。
肝心の
ウィンドウプロシージャー
を、どこに設置すればよいのかが分かりません。
適当なヘッダに書き、それをインクルードしても
「1 つ以上の複数回定義されているシンボルが見つかりました。」
という関係のエラーが15個ほど出て、出来ません。
既に定義されているという扱いになっているのならば、どこかにあると思うのですが、どこにあるのでしょう・・・?
というより
これはみた感じウインドウ毎に作るべき関数・・・ですよね?
その前提があっているならば、これは既にあるものと同じものを再定義したと判定され、競合してしまっているということでしょうか?
No.3ベストアンサー
- 回答日時:
こんばんは。
補足頂きました。う~む、wndproc.h と wndproc.cpp に分けると良さそうです。
ヘッダーに実体を書いて複数回インクルードすると、 「1 つ以上の複数回定義されているシンボルが見つかりました。」と出てしまいます。関数のプロトタイプと実装は別々にします。
また、同じ動きをするウィンドウを複数作成するならば、同一のプロシージャーを共有する事も出来ます。
分割の仕方は以下を参考程度に。
wndproc.h
+--------------------------------------------------------------------------------------
#ifndef __WNDPROC_H__
#define __WNDPROC_H__
#include<windows.h>
#pragma comment(lib, "user32.lib")
extern LRESULT CALLBACK Win32ChildProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
#endif
--------------------------------------------------------------------------------------+
wndproc.cpp
+--------------------------------------------------------------------------------------
#include"wndproc.h"
LRESULT CALLBACK Win32ChildProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch(uMsg)//ココでメッセージを引っ掛ける
{
case WM_KEYDOWN:
{
//例えばキーが押された
}
}
return ::DefWindowProc(hWnd, uMsg, wParam, lParam);
}
--------------------------------------------------------------------------------------+
Form1のソース又はヘッダーファイルの一番上で、
#include"wndproc.h"
とする。此れで出来る筈。
なるほど!!
「いつも無意識でやってたアレですか」
状態です!
ウインドウプロシージャという概念は今日初めて知ったので、なにか特別なものなのか・・・?と思ってしまいましたが
普通の関数と同じように考えればいいのですね!
そういえば、今までそういう事が1,2回あったような気がしますが
「ヘッダーに実体を書いて複数回インクルードすると」
再現される、というわけでしたか。
分かってるのとそうでないのでは違いは明白でしょう。
情報ありがとうございます♪
つまり概要としては
WNDCLASSEXで好きなウインドウの性質を作って
CreateWindowExの2つ目のプロパティでそれにつけた名前をもとにその性質をもったウインドウを生成する。
そしてそのウインドウが呼び出すプロシージャは
WNDCLASSEXの
lpfnWndProc
に設定しておくことで、あとはOSがそのような動作をしてくれるようになる・・・というAPIってわけですね。
確かにそこを同じにすれば、同じ動作をするものも出来ますね!
このウインドウ専用にクラスを作ろうと思っていましたので
きっとそのメソッドとして作る事も出来ますよね。
とりあえず、マウス左・右クリックにメッセージボックスを割り当て
動作確認できました。
これでまた大きな一歩を進めました。
ありがとうございます!
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・人生のプチ美学を教えてください!!
- ・10秒目をつむったら…
- ・あなたの習慣について教えてください!!
- ・牛、豚、鶏、どれか一つ食べられなくなるとしたら?
- ・【大喜利】【投稿~9/18】 おとぎ話『桃太郎』の知られざるエピソード
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
vbaから他のアプリを終了
-
他のウィンドウのボタンを自動...
-
デスクトップ上のアイコンの位...
-
メッセージボックスの選択ボタ...
-
有効でないウインドウハンドル...
-
メッセージハンドラ
-
マウスの状態の取得
-
マインクラフト(pc版)で座標...
-
エクセルで作った新しいウイン...
-
コントロールの書式設定で、“コ...
-
作成したウインドウのサイズを...
-
Minecraft 統合版(PC)の描画距...
-
コンボボックス内の文字サイズ変更
-
「アイテムは収集されました」...
-
ブレゼンハムのアルゴリズムに...
-
カーソルが自分のウィンドウか...
-
C言語 配列で座標
-
グラフの交点の求め方(Excel)
-
スクロールバーを点滅させない方法
-
panelのスクロール表示について
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
vbaから他のアプリを終了
-
他のウィンドウのボタンを自動...
-
メッセージハンドラ
-
VBAでコントロールのハンドルを...
-
msgboxの表示位置
-
メッセージボックスの選択ボタ...
-
SetWindowText関数について
-
VBA 複数セルが空白なら印刷さ...
-
WM_NCLBUTTONUPについて
-
デスクトップ上のアイコンの位...
-
点滅で知らせる方法
-
チェックボックスのキーダウン...
-
CloseHandle()
-
Excel VBA で外部アプリケーシ...
-
WM_CLEARなど使えないメッセー...
-
マウスの状態の取得
-
DEVICECHANGE() の受け取り
-
SendMessage で ESC など
-
VBでのハンドルの使い方
-
VB.netでSendMessageを使用して...
おすすめ情報