CWindowImpl DECLARE_WND_SUPERCLASSについて

[戻る]
谷内田 2009/11/26(木) 10:34:11
お世話になります。

VC6ですが(またはVC2005)
class メインクラス : public CWindowImpl<メインクラス>
{
public:
    DECLARE_WND_SUPERCLASS(NULL,登録済みクラス)

という感じで作成されたウィンドウクラスがあるのですが
ここの登録済みクラスで使用していたマイクロソフトのものでないクラスが
バージョンアップでなくなってしまいました。
つきまして変わりのクラスを自作したいのですがどのようにして登録済みクラスを
作成してよいか分かりません。DLLで作成するのでしょうか・・?
基本的にメインクラスのほうでDefWindowProcを呼んだ場合や

LRESULT メインクラス::OnPaint(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& 
bHandled)
{
    bHandled = FALSE;
とした場合に追加メッセージ処理を行いたいだけです。

またはDECLARE_WND_SUPERCLASSを使わずに
メインクラスのDefWindowProcを呼んでる箇所やbHandled = FALSE;の場合に
メインクラスのほうに追加処理を挿入したほうがよいでしょうか?

よろしくお願いします。

仲澤@失業者 2009/11/26(木) 11:11:15
「メインクラス」なるものが大量に使うコントロールなどの場合は
「登録済みクラス」を自作しても良いと思います。以下は方法です。

「登録済みクラス」で設定していたWNDCLASSEX構造体の設定内容を調べる必要が
あります。まず以前のアプリケーションを立ち上げて、「メインクラス」が表示
しているウインドウのウインドウクラスの設定内容をSPY++で確認します。
クラス名称は変更したものを使用します。不足しているアイコンなどは作成します。
その内容でRegisterClass()し、SDKコードでウインドウが出ることを
確認できれば、第一段階は完了です。
次に提示のコードの「登録済みクラス」名称を「変更した新しいクラス名称」
に変更してビルドします。
最後に以前と違う動作をしている部分を「変更した新しいクラス名称」の
コールバック以降で修正します。

しかし、「メインクラス」なるものがメインウインドウ等のように1〜数個
程度なら、スーパークラス化をあきらめて、「登録済みクラスのコールバック
がやっていた作業を追加修正したほうが早いでしょう。

いずれにしても、自作又はSDKで提供されていないクラスのスーパークラスや
サブクラスを作ってしまうのはおおらか過ぎるので今後はやめたほうが
良いと考えられます。

谷内田 2009/11/26(木) 14:37:32
お返事ありがとうございます。

WNDCLASSは設定できそうですがHINSTANCE hInstanceを使うので
このメインクラスはDLLですがSDKコードとは以下のところでしょうか?

// DLL エントリ ポイント
extern "C"
BOOL WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID /*lpReserved*/)
{
    if (dwReason == DLL_PROCESS_ATTACH)
    {
        _Module.Init(ObjectMap, hInstance, &LIBID_AAALib);
        DisableThreadLibraryCalls(hInstance);

このへんで登録?

    }
    else if (dwReason == DLL_PROCESS_DETACH)
        _Module.Term();
    return TRUE;    // ok
}

コールバック関数は
WNDCLASS.lpfnWndProc = MainWndProc;
としてMainWndProcもSDKコードのソースの辺りに追加する感じでしょうか?

よろしくお願いします。

仲澤@失業者 2009/11/26(木) 15:40:22
え〜と、やってみましたか(質問)。

1.WNDCLASSEX::hInstanceが本当に必要か(0でも良いのか)試しましたか。
  このてのレガシーなやつは試してみることが重要です。

2.CreateWindowEx()で使用するクラス名称はRegisterClassEx()で設定した
  ものと同じです。この関係から両者をどこで行うかは自明だと思われるのですが
  どうでしょう。

3.「SDKコードで」と言ったのはMFCでは(厳密には)クラス名称が設定できない
  ので、という意味です。それともMFCと戦うことを選択しますか。

4.先は長いですよ。最初からDLLでやるつもりなのでしょうか、
  テストなどはEXEプロジェクトで十分ですよねぇ。

谷内田 2009/11/26(木) 16:15:44
さきほど書いたものを試しました。
一応うまくコールはされるようですが問題がでました。
登録したクラスに変数を持ちたいのですがメインクラスを複数生成した場合に
それに対応するように持てないと思います。

1.と2.からメインクラスをCreateWindowする前にRegisterClassをしておけばよい感
じでしょうか?

メインクラスに対応して登録クラスが変数をもつには登録クラスをDLLで作成して
CreateWindowする前にライブラリロードしておく感じでしょうか?

構成は現在、大元から親クラスを1こ生成して
親クラスからメインクラスを(複数)生成する感じです。(メインというか子でした)

3.はプロジェクト設定を見るとMFCを使用しないでした。

4.については一応DLL呼び出しEXEのようなものがありますで大丈夫かと思います。

谷内田 2009/11/26(木) 18:40:11
普通のDLLのBOOL APIENTRY DllMain
でRegisterClassをしてみてメインクラス作成前でLoadLibraryしてみましたが
メインクラスのウィンドウの作成に失敗してしまいました。
DLLの場合なにか特殊なんでしょうか?

仲澤@失業者 2009/11/30(月) 13:58:39
>1.と2.からメインクラスをCreateWindowする前にRegisterClassをしておけばよい>じでしょうか?

何度も言うようで申し訳ないのですが。登録されていないウインドウクラスを
使用してウインドウは作れないということから自明です。

レガシーを疑ってくださいというのはHINSTANCEなんぞ無くても
ウインドウクラスは登録できるということ言いたいだけです。
この件は試しましたか。

>登録したクラスに変数を持ちたいのですがメインクラスを複数生成した場合に
>それに対応するように持てないと思います。

クラスの属性を拡張するための領域は、クラス拡張BYTE(cbClsExtra)に必要な
BYTE数を設定してSetClassLongPtr()等を使います。HWND毎に持ちたい場合は
ウインドウ拡張BYTE(cbWndExtra)に必要な量を設定してSetWindowLong()等を
使います。でも、経過から類推すると本件とは多分無関係だと考えられます。

>4.については一応DLL呼び出しEXEのようなものがありますで大丈夫かと思います。

DLLを気軽にデバッグできるスキルがあれば問題はありません。
しかし、

>普通のDLLのBOOL APIENTRY DllMain
>でRegisterClassをしてみてメインクラス作成前でLoadLibraryしてみましたが
>メインクラスのウィンドウの作成に失敗してしまいました。
>DLLの場合なにか特殊なんでしょうか?

のような事になるので、EXEでやってください。とアドバイスしているのです。
この件はやってみましたか。

谷内田 2009/12/01(火) 18:44:34
[[解決]]
スーパークラス化は難しい問題がでたので
最終的にメインクラスに処理追加で比較的問題なくできました。

>レガシーを疑ってくださいというのはHINSTANCEなんぞ無くても
>ウインドウクラスは登録できるということ言いたいだけです。
>この件は試しましたか。

なくても大丈夫でした。

>クラスの属性を拡張するための領域は、クラス拡張BYTE(cbClsExtra)に必要な
>BYTE数を設定してSetClassLongPtr()等を使います。HWND毎に持ちたい場合は
>ウインドウ拡張BYTE(cbWndExtra)に必要な量を設定してSetWindowLong()等を
>使います。でも、経過から類推すると本件とは多分無関係だと考えられます。

いろいろ勉強になります。

>のような事になるので、EXEでやってください。とアドバイスしているのです。
>この件はやってみましたか。

別の機会に試してみます。

いろいろアドバイスありがとうございました。

古いスレッドには追加発言できません。