映画のエンドロール観る派?観ない派?

VC++2008のWindowsフォームアプリケーションで
WindowsAPIのウインドウを作って使いたいのですが、この場合どのようにすれば
普通にフォームアプリケーションに新しい子ウインドウを表示させる

Form^ a;
a->Show();

のように
メッセージループ(?)をさせる事が出来るのでしょうか?
WindowsAPIの解説サイトや本などを見ても、大抵はそれのみの解説のため、while文で自身に対してそうするだけでいいようなのですが

同じようにフォームアプリケーションの子ウインドウとしてやろうとすると、そうするだけでは当然メインフォーム側の操作が出来なくなってしまいます。

どのように実現したらいいのでしょうか?
また、そもそも上記のように普通に子ウインドウを作った場合は、どのように実現されているのでしょうか?

A 回答 (3件)

API関数CreateWindowExでウィンドゥを作成すれば、OSが勝手にメッセージループを呼び出します。



もちろん、デフォルトのメッセージループは標準の事だけしかせず、何もしてくれないので、メッセージループをフックして、それなりの事を書いてあげないとなりません。

親は「どっかに勝手に動いてる子が居る」って事だけを意識していれば良いです(終了時に後始末、とか)
    • good
    • 0
この回答へのお礼

なるほど、ありがとうございます!

ということは、実行中は、これが来たらこうするというのを書けばいいだけ、という事ですか。
ではその・・・具体的な処理内容は、この場合だとどこにどういう風に書けばいいのでしょうか?

かなりの概要的な言い方をすると
ウインドウ用のクラスを別途作っておいて
そのインスタンスを、親となるフォームの中に作っておく、という事で実現できるのでしょうか・・・?

お礼日時:2009/01/23 17:25

 こんにちは。



>>そもそも上記のように普通に子ウインドウを作った場合は、どのように実現されているのでしょうか?
 ウィンドウプロシージャーという関数に対し、メッセージコールバックが掛かる様になっています。

//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);
}
    • good
    • 0
この回答へのお礼

こんにちは。
おおお!ありがとうございます!
とりあえず、メンバとして用意しコンストラクタでwin32でウィンドウを開くメソッドを呼び出し
ウインドウを開くのは出来ました!

でも残りの一歩が分かりません。
肝心の
ウィンドウプロシージャー
を、どこに設置すればよいのかが分かりません。

適当なヘッダに書き、それをインクルードしても
「1 つ以上の複数回定義されているシンボルが見つかりました。」
という関係のエラーが15個ほど出て、出来ません。

既に定義されているという扱いになっているのならば、どこかにあると思うのですが、どこにあるのでしょう・・・?

というより
これはみた感じウインドウ毎に作るべき関数・・・ですよね?

その前提があっているならば、これは既にあるものと同じものを再定義したと判定され、競合してしまっているということでしょうか?

お礼日時:2009/01/23 18:55

 こんばんは。

補足頂きました。
 う~む、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"
とする。此れで出来る筈。
    • good
    • 0
この回答へのお礼

なるほど!!
「いつも無意識でやってたアレですか」
状態です!
ウインドウプロシージャという概念は今日初めて知ったので、なにか特別なものなのか・・・?と思ってしまいましたが
普通の関数と同じように考えればいいのですね!


そういえば、今までそういう事が1,2回あったような気がしますが
「ヘッダーに実体を書いて複数回インクルードすると」
再現される、というわけでしたか。
分かってるのとそうでないのでは違いは明白でしょう。
情報ありがとうございます♪


つまり概要としては

WNDCLASSEXで好きなウインドウの性質を作って
CreateWindowExの2つ目のプロパティでそれにつけた名前をもとにその性質をもったウインドウを生成する。

そしてそのウインドウが呼び出すプロシージャは
WNDCLASSEXの
lpfnWndProc
に設定しておくことで、あとはOSがそのような動作をしてくれるようになる・・・というAPIってわけですね。

確かにそこを同じにすれば、同じ動作をするものも出来ますね!

このウインドウ専用にクラスを作ろうと思っていましたので
きっとそのメソッドとして作る事も出来ますよね。

とりあえず、マウス左・右クリックにメッセージボックスを割り当て
動作確認できました。

これでまた大きな一歩を進めました。
ありがとうございます!

お礼日時:2009/01/23 20:40

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!