ページ 13

「DLL側からコントロールの色変更」について

Posted: 2006年4月04日(火) 16:27
by KICO
何時も、お世話に成っています。

DLL側から指定したコントロールの色変更が出来ないのですが、どの様にすれば良いのでしょうか?
宜しくお願いします。

Re: 「DLL側からコントロールの色変更」について

Posted: 2006年4月04日(火) 17:29
by ノッチ
あのコードだと多分自前で描画した後に通常の描画が行われているのでは
ないかと思います。
WH_CALLWNDPROCをWH_CALLWNDPROCRETに変えてみたらどうでしょうか?
それともフックじゃできないのかな?

「DLL側からコントロールの色変更」について

Posted: 2006年4月04日(火) 18:07
by KICO
ノッチ様、何時もありがとう御座います。
あのコードだと多分自前で描画した後に通常の描画が行われているのでは
ないかと思います。
WH_CALLWNDPROCをWH_CALLWNDPROCRETに変えてみたらどうでしょうか?
WH_CALLWNDPROCRETに変えてみましたが、ダメでした。

If lParam->lParam=STATIC1 Then f=1: tc=&HFF: bc=&HFFFF: Beep(10000,100)
確認したところWH_CALLWNDPROCではSTATIC1を捕らえる事は出来ますが、
WH_CALLWNDPROCRETでは、捕らえられませんでした。

宜しくお願いします。

Re: 「DLL側からコントロールの色変更」について

Posted: 2006年4月04日(火) 21:41
by ノッチ
> If lParam->lParam=STATIC1 Then f=1: tc=&HFF: bc=&HFFFF: Beep(10000,100)
> 確認したところWH_CALLWNDPROCではSTATIC1を捕らえる事は出来ますが、
> WH_CALLWNDPROCRETでは、捕らえられませんでした。

WH_CALLWNDPROCでそれぞれの関数の戻り値をmsgbox等で確認して
関数が成功しているかを確認して見て下さい。
WH_CALLWNDPROCのMSDNの説明に「CallWndProcフックプロシージャは、
メッセージを調べることはできますが、メッセージの修正はできません。」
という文があったのでそこで処理を行うことができないのかもしれません。
他にもWH_GETMESSAGEというフックもあり、それには「GetMsgProcフック
プロシージャは、メッセージを調べたり修正したりできます。」とあるので
こちらであれば処理が可能かもしれません。

「DLL側からコントロールの色変更」について

Posted: 2006年4月04日(火) 22:16
by KICO
ノッチ様、ありがとう御座います。
WH_CALLWNDPROCでそれぞれの関数の戻り値をmsgbox等で確認して
関数が成功しているかを確認して見て下さい。
「それぞれの関数」とは、SetBkMode(), SetBkColor(), SetTextColor()等の事でしょうか?
WH_CALLWNDPROCのMSDNの説明に「CallWndProcフックプロシージャは、
メッセージを調べることはできますが、メッセージの修正はできません。」
という文があったのでそこで処理を行うことができないのかもしれません。
解説に、そう書いてありますね。見落としていました。
他にもWH_GETMESSAGEというフックもあり、それには「GetMsgProcフック
プロシージャは、メッセージを調べたり修正したりできます。」とあるので
こちらであれば処理が可能かもしれません。
「GetMsgProcフック」も試しましたが、WM_CTLCOLORSTATICが捕らえられませんでした。

宜しくお願いします。

Re: 「DLL側からコントロールの色変更」について

Posted: 2006年4月04日(火) 23:15
by ノッチ
試しもせずに想像で答えたのがことごとく外れたようです。
確実ではないですが、フックプロシージャからの変更はできそうにないです。
そこで裏技的な方法で、WH_CALLWNDPROCでフックをインストールする。
フックプロシージャでlParam->hwndに対しサブクラス化する。
と言う方法があります。(実際にそういったソフトがあります)
この方法であれば別プロセスであってもサブクラス化が可能になります。

【注意点1】
フックインストール時にGetWindowThreadProcessIdで
取得したスレッドIDを使用してSetWindowsHookExを呼び出す。

コード: 全て選択

例:
ThreadID=GetWindowThreadProcessId(STATIC1, NULL)
SetWindowsHookEx(WH_CALLWNDPROC,AddressOf(CallWndProc),hInst,ThreadID)
【注意点2】
CallWndProcで何度もサブクラス化しないようにグローバルにフラグ用の
変数を用意して1度だけ処理を行うようにする。

これでどうでしょう?

「DLL側からコントロールの色変更」について

Posted: 2006年4月04日(火) 23:46
by KICO
ノッチ様、ありがとう御座います。
そこで裏技的な方法で、WH_CALLWNDPROCでフックをインストールする。
フックプロシージャでlParam->hwndに対しサブクラス化する。
と言う方法があります。(実際にそういったソフトがあります)
この方法であれば別プロセスであってもサブクラス化が可能になります。
サブクラス化だと確か対象コントロール分用意するはずで、この場合「STATIC1」
一つですが、複数個に成る場合どうすれば良いのでしょうか?

宜しくお願いします。

Re: 「DLL側からコントロールの色変更」について

Posted: 2006年4月10日(月) 00:03
by ノッチ
サブクラス化だと確か対象コントロール分用意するはずで、この場合「STATIC1」
一つですが、複数個に成る場合どうすれば良いのでしょうか?

宜しくお願いします。
大変長らくお待たせしました。
内容は自由に改変してかまいませんので。といってもバグとかまだありそう
なので改変しないとだめだと思いますが。
KICOさんがそれぞれのコントロールでどういった処理をしたいのかが
不明ですが、単純にサブクラス化するコントロールが決まっているので
あれば内容を少しいじるだけで大丈夫だと思います。

DLLのコード 呼び出しのexe側 また出張でホテル生活なのでしばらくはネット環境ありの予定です。

「DLL側からコントロールの色変更」について

Posted: 2006年4月10日(月) 22:28
by KICO
ノッチ様、ありがとう御座います。(休日中考えて頂いていたんですネ)

コード拝見しましたが、凄く難しくて理解するのに時間が掛かりそうです。
後ほど色々と質問させて頂きますが、取敢えず一つ、FindWindow()で指定されていますが、
特定のコントロールの指定は出来るのでしょうか?
「NUM_SUBCLASS_WNDの同時にサブクラス化できるウィンドウ数」とは、
"コントロールのウィンドウ"という事ではないのですか?
KICOさんがそれぞれのコントロールでどういった処理をしたいのかが
不明ですが、単純にサブクラス化するコントロールが決まっているので
あれば内容を少しいじるだけで大丈夫だと思います。
指定したコントロールの色変更をDLL側からしたいのですが例えば、「STATIC1~STATIC10は、青色。STATIC11~STATIC20は、黄色。 EDIT1~EDIT20は、灰色。」という様に。

「また出張でホテル生活・・・。」 よく出張されているみたいで大変ですね、
お仕事ガンバって下さい。 (^o^)


宜しくお願いします。

Re: 「DLL側からコントロールの色変更」について

Posted: 2006年4月11日(火) 00:29
by ノッチ
特定ウィンドウのコントロールだけであれば、
下記コードを使用してください。
前回使用方法を記述してなかったのですが、
変更したい対象の「親」ウィンドウハンドルを指定して
SetSubClass を呼び出します。
サブクラスを終了したい時には
EndSubClass を呼び出します。

上記DLLのコードではABで作成した"test"というキャプションのウィンドウに
配置されているStaticコントロール5つの色をそれぞれ変更します。

別プロセス間のデータはグローバルであっても使用できないようなので、
GetWindowLong(GWL_ID)でコントロールのIDを取得し、そのIDを使用して
色分けを行っています。

> 後ほど色々と質問させて頂きますが
とのことですが、遠慮なくどうぞ!

「DLL側からコントロールの色変更」について

Posted: 2006年4月11日(火) 12:46
by KICO
ノッチ様の方では正常に表示されているみたいですが、私の方では
DLL内でグルグル回っているみたいでウィンドウが表示されません?

それと、以前から機会があったらお聞きしたかったのですが、
「構造体を指定した配列変数」の初期化についてなのですが
例えば、"Dim scs[10] As SUBCLASSSTRUCT"を全て初期化しようとする場合、
"For i=0 to 10: ZeroMemory(VarPtr(scs), Len(scs)): Next" としていますが
"ZeroMemory(VarPtr(scs[0]), Len(scs[0])*11)" としては、
マズイ(必ずしも連続しているとは限らない為)でしょうか?
又、配列変数のDim宣言時には常にNULL(0)に成っているとは限らないのでしょうか?
と言うのもDim宣言の直後に "ZeroMemory()"等で初期化されているのを時々見受けられるからです。

宜しくお願いします。

Re: 「DLL側からコントロールの色変更」について

Posted: 2006年4月11日(火) 23:15
by ノッチ
> ノッチ様の方では正常に表示されているみたいですが、私の方では
> DLL内でグルグル回っているみたいでウィンドウが表示されません?

前のDLLはあくまでもDLLです。
前のコードをそのまま使うには、ABでtestという名前で新規プロジェクトを
作成してウィンドウにStaticを5つ配置、F7でコンパイルしたexeを実行して
おきます。->①
別のプロジェクトを新規作成して、プロジェクトのフォルダ内に作成したDLLを
置いて、WM_CREATE部分にSetSubClass部分、WM_CLOSEにEndSubClass部分を
追加します。->②
するとすでに実行しているtest.exe(①)のウィンドウに配置したStaticの文字色が
変化します。
②を終了させて①の画面を更新(画面を隠して再表示)させると文字色が黒になります。(サブクラス化解除)

これでうまくいかないようであればもう一度質問してください。

> それと、以前から機会があったらお聞きしたかったのですが、
> 「構造体を指定した配列変数」の初期化についてなのですが
> 例えば、"Dim scs[10] As SUBCLASSSTRUCT"を全て初期化しようとする場合、
> "For i=0 to 10: ZeroMemory(VarPtr(scs), Len(scs)): Next" としていますが
> "ZeroMemory(VarPtr(scs[0]), Len(scs[0])*11)" としては、
> マズイ(必ずしも連続しているとは限らない為)でしょうか?

これは構造体と配列から考えると、構造体の順番通り、配列の順番通りに
メモリが確保されるので問題ないはずです。
が、もしかしたら4Byte境界(64bit環境では8Byte?)で丸めるという処理が入る
かもしれません。
そうすると、構造体の中にByteやWordが含まれているときれいに初期化されない
かもしれません。
恐らくは問題ないとは思いますが、確実性を求めるのであれば上記のように
Forで初期化するのが良いと思います。
(この程度で速度的に問題があるのであればそもそも仕様を考え直した方が
早いかと)

> 又、配列変数のDim宣言時には常にNULL(0)に成っているとは限らないのでしょうか?
> と言うのもDim宣言の直後に "ZeroMemory()"等で初期化されているのを時々見受けられるからです。

ABの変数確保方法は、スタックと呼ばれるメモリ領域を使用したごく一般的な
もので、サブルーチン(関数)を呼び出したり変数を確保することで
さまざまな用途に使用されるメモリである為、宣言時は内容が不確定です。
(HeapAlloc APIやalloc関数を使用したメモリのようなもの)
HEAP_ZERO_MEMORYやcallocを使用して

Dim scs As *SUBCLASSSTRUCT
scs=calloc(***)

のようにすると0で初期化されています。(これは説明するまでもないと思いますが)

「DLL側からコントロールの色変更」について

Posted: 2006年4月12日(水) 00:45
by KICO
ノッチ様、ありがとう御座います。

①(test.exe)を実行した後②を実行、色が変化しないので①のウィンドウにカーソルを置く
又は、アクティブにすると①がエラーに成り強制終了します。

「配列変数」の初期化についてですが、良く解りました。


宜しくお願いします。

変数の初期値

Posted: 2006年4月12日(水) 19:06
by イグトランス
ABの場合,ZeroMemoryせずとも全ての変数は初めから0になっています。
ただ,明記された仕様ではないので,それを当てにしなかったり知らなかったりで,私も含め明示的にZeroMemoryを使う人もいるのです。

Re: 変数の初期値

Posted: 2006年4月12日(水) 19:28
by KICO
イグトランス様、何時もありがとう御座います。

> ABの場合,ZeroMemoryせずとも全ての変数は初めから0になっています。

ABでは基本的に、Dim宣言時にNULL(0)になっているという事ですネ。
良く解りました。


また、宜しくお願いします。(^_-)