【C++】マイナーGUIツールキットat TECH
【C++】マイナーGUIツールキット - 暇つぶし2ch446:デフォルトの名無しさん
08/11/09 01:47:00
>>445

ググって、VirtualAllocこれが何かはわかった。
(呼び出し側プロセスの仮想アドレス空間に領域を確保)

が、そのほかの部分がわからない。

もうちょっと噛み砕いてお願いしたい。

447:デフォルトの名無しさん
08/11/09 02:04:48
とりあえず他でやって欲しい。

448:デフォルトの名無しさん
08/11/09 02:05:45
マイナーGUI(ラッパか・・・)作ってるからいいんじゃね?

449:デフォルトの名無しさん
08/11/09 02:27:18
>>446
君がどういうレベルかわからないと説明は難しい。
stdcallとcdeclは知っている?
clのABIはthiscallでECXにthisが入るのは知っている?

450:デフォルトの名無しさん
08/11/09 02:41:11
私のレベルは、簡単なものならAPIをガリガリでモノを作れる。
MFCは使ったことなし。

>stdcallとcdeclは知っている?
これは名前は知っている。

>clのABIはthiscallでECXにthisが入るのは知っている?
これは、知らない。
cl・・・コンパイラ?
ABI・・・アプリケーション・バイナリー・インターフェイス?
thiscall ≒ cdecl?
ECX・・・アセンブリは全く知らない

つまり、アセンブリを知らないとできないってこと?orz



451:デフォルトの名無しさん
08/11/09 03:14:18
>>450
アセンブリと言っても別に難しい知識は必要ない。
C言語が使えるんなら、レジスタとスタックの操作、
つまりmovとpushくらいは3分でわかるはず。

そして引数がスタックに積まれることが理解できれば良い。
そのスタックをどこで戻すかの違いがstdcallとcdecl。
インスタンスメソッドに対してはインスタンスが引数として扱われる。
それがcl(VC++のコンパイラ)ではECXで渡されるということ。
ちなみにgccだと第一引数としてスタックに積まれる。
こういう呼び出し規約のことをABIと呼ぶ。

なぜこんな知識が必要か?
それはインスタンスメソッドに対してコールバックさせるため。
実際にATLではこの方法が使われている。
ハッシュで済ませるんなら必要ないんだけど、
外部に委譲させるときに悩むことになる。

452:デフォルトの名無しさん
08/11/09 03:23:19
ふと疑問に思って昔作ったGUIクラスをひっぱりだして覗いてみたら

SetWindowLong( hWnd, GWL_USERDATA, (int)this );
みたいな感じのを使ってた。ハンドルと32bitデータを関連付けられるらしい。
で、Windowプロシージャで
GetWindowLong( hWnd, GWL_USERDATA );
を使って、ハンドルから対応クラスのポインタをひっぱってきて
Window別のイベントを処理してた。なつかすぃ。

453:デフォルトの名無しさん
08/11/09 03:33:48
>>452
その方法だとたとえばウィンドウ上でIMEの入力をしているときに
候補の上でホイール回したりしてIMEが作ったhWndが飛んでくると
不正なポインタに飛ばすことになって落ちるよ。
結局、登録されたhWndかどうかチェックするとハッシュになってしまう。

454:デフォルトの名無しさん
08/11/09 07:15:09
>>445
ウィンドウインスタンスごとにRegisterClassExって何か違うと思う。
ATLでやってるのは、StartWindowProcってのを登録しといて、
StartWindowProcの中でサンクつくって、次回以降はそれが呼ばれるようにする、っていう方法だったと思う。

>>453
俺はIME触ったこと無いから実際はどうなのか知らないんだけど、
そんなことがあったらそれIMEのバグじゃねーの?

455:デフォルトの名無しさん
08/11/09 09:30:36
同じくで、サンク作る方法は自分でも書いたことあったけども>>454の意味はちまちまわからんとこが。
ATLのソースか、エディタのGreenPadがそんな方法使ってたから見てみてもいいかも。
わかりにくい上に機械語直接埋め込むから試しに自分でラッパ書いてみる、って段階ではどうかと思うが、早いし。

ウィンドウハンドルとthisを関連づける方法はGWL_USERDATAの他にSetProp/GetPropAPIもある。

URLリンク(hp.vector.co.jp)
URLリンク(hilbert.elcom.nitech.ac.jp)

一応この辺がその辺の話。

456:デフォルトの名無しさん
08/11/09 10:50:11
454だけど、実際にATLがどうやってるのかは>>455のリンク先が詳しいのでそっち見てね。
あと、WndProcからthisを手に入れる方法を適当にまとめてみた。他にも方法あるかも。

どこにHWND↔thisの対応を入れておくか
・Set/GetWindowLongPtrを使う(GWLP_USERDATAを使うのか、cbWndExtraで確保しとくのか)
・Set/GetPropを使う(キーは文字列かATOMか)
・ハッシュテーブルを使う(排他制御はどうすんのか)
・サンクを使う(CPUのアーキテクチャごとにry)

どのタイミングでHWND↔thisを関連づけるか
・WM_CREATEで(thisはCreateWindowの最後の引数か、グローバル変数から)
・最初にWndProcが呼ばれた段階で(thisはグローバル変数から)
・WH_CBTとかWH_CALLWNDPROCフックで(thisはグローバル変数から)
・そもそもWM_CREATEイラネ、CreateWindowを呼んだ後で
ただしグローバル変数にはTLSも含む

457:デフォルトの名無しさん
08/11/09 12:24:53
いくつか意見がでてるけど、個人的にはハッシュが一番楽じゃない?と思う。

std::map<HWND,[基底クラスのポインタ]> g_controlList;

LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
  基底クラス *p基底クラス = g_controlList[ hWnd ];

  // コントロール別イベント処理
  p基底クラス->OnEvent(msg, wParam, lParam);
}

最近C++書いてないんで色々間違ってそうだけど、キモはこんな感じかと。
ここは、より良い方法がでてきたら差し替えることにして
次へ進んだ方が本人の為になるし、スレ的にも面白いw

458:デフォルトの名無しさん
08/11/09 13:50:14
>>454
インスタンスごとにクラスを登録しているのはWindows Formsだね。

459:デフォルトの名無しさん
08/11/09 18:40:07
この流れを見てるとこのスレの住人はやっぱり結構自分ラッパを書いてしまっているんだなあと感じて親近感がw
しかし>>450は付いてきているのか。周りが凄い盛り上がってしまってるけど。

460:デフォルトの名無しさん
08/11/09 21:38:28
>>450は単語一個一個調べたり、根が真面目そうなんで、
今、大量の情報がドカドカ出てきたので知らん部分をググってる最中じゃない?
期待がプレッシャーにならない程度にマターリ待つのが良いかと。

俺もラッパ作ちゃった1人なんだが、結局デザイナーツールの作成が面倒で
活用には至らなかった。
その辺までしっかり作った人っているの?

461:デフォルトの名無しさん
08/11/10 00:28:53
なぁ、>445 の方法って、ネットで探しても情報ないのな。
ATLのソース読んでみようと思ったけど、どこから読んだらいいのかわかんねw

>450 は初心者っぽいしきつい気がするのは俺だけか?


そういや、昔、CマガでGUIライブラリを作るってのがあったが
あれは参考にならないか?
もう、手に入らないけど。

462:デフォルトの名無しさん
08/11/10 02:05:47
>>460
> その辺までしっかり作った人っているの?

WideStudioってきもいけど凄いよね

463:デフォルトの名無しさん
08/11/10 06:11:25
>>461
ATLについては>>455
>>445の言ってるのはATLじゃなくてWindows Formsのことらしい

464:デフォルトの名無しさん
08/11/10 07:58:51
『組み込みGUI(ウィンドウ・システム)環境の設計と実装』って本
読んだことある人います? おもしろい?

465:デフォルトの名無しさん
08/11/10 08:11:08
>>463
>455は手軽にthunk作るやり方。
ATLはCDynamicStdCallThunkが__AllocStdCallThunkの確保した領域に機械語つっこんでるぞ。

466:デフォルトの名無しさん
08/11/10 13:35:58
>>450
適当にサンクを実装してみた。良かったら参考にしてみて。
URLリンク(www.yourfilehost.com)

>>451
stdcallとthiscallの変換があるから単純にECXに代入するだけじゃダメだぞ?
まあそれでも動くけどさ、ちょっと気持ち悪いよね。

467:デフォルトの名無しさん
08/11/10 15:47:24
>>464
フレームバッファ直描きでウィンドウシステムを作る本だよ。
OSを作ったりとか、LinuxでXを使わないGUIを作ったりとか、
そういうことに興味がある人には面白いと思う。
Windowsアプリを作るのにはほとんど参考にならない。

468:デフォルトの名無しさん
08/11/10 21:28:35
一つずつ

>>451

>つまりmovとpushくらいは3分でわかるはず。
mov・・・ジスタやメモリに、データの転送を行う
push・・・スタックにデータを積む

>そのスタックをどこで戻すかの違いがstdcallとcdecl。
このことでいいのかな?
URLリンク(www.ne.jp)

>ECX
レジストリと
こんな場所がある、程度でいいのかな?



469:デフォルトの名無しさん
08/11/10 21:32:35
>>452
>>453
>>454
調べたらこんな頁を発見
URLリンク(qwerty.s2.xrea.com)

サンク(thunk)って、調べても情報がないな。


470:デフォルトの名無しさん
08/11/10 21:34:28
>>455

いま、ここまで

参照先のリンクの内容を理解するのに苦労している。
正直、難しい。

471:デフォルトの名無しさん
08/11/10 22:41:30
>>469
wikipediaにあったぞ
URLリンク(en.wikipedia.org)

472:デフォルトの名無しさん
08/11/11 17:08:05
WindowsXP SP2のDEPでATLのThunkが問題になってたような気がするんだけど、
あれは何でなんだろ?

473:デフォルトの名無しさん
08/11/11 17:22:32
>>472
ウィルス等がバッファオーバーフローでヒープに不正コードを埋め込むことの対策として
ヒープのコードを実行できなくしたのがDEP。

ATLではサンクをHeapAlloc領域でやっていたため引っ掛かることになった。
今のATLはVirtualAllocでPAGE_EXECUTE_READWRITEで確保するため問題ない。

474:472
08/11/11 20:27:35
>>473
なるほど、わかりやすい説明サンクスです。

475:デフォルトの名無しさん
08/11/13 03:52:36
おまえら!
言いたいのをガマンしてるなら、代わり俺が言ってやるよ!
あくまでもおまえらの代弁だからな!俺が言いたいワケじゃないんだからな!





なるほど、わかりやすい説明Thunkです。

476:デフォルトの名無しさん
08/11/13 07:05:21
さみぃw

477:デフォルトの名無しさん
08/11/17 23:11:46
こんな方法どうやって勉強しました?

478:デフォルトの名無しさん
08/11/18 22:33:44
>>477
Windows 3.1の頃(15年前)からプログラム作ってたら嫌でも身に付く

479:デフォルトの名無しさん
08/11/19 18:52:55
class window
{
public:
 static window *m_this;
 static LRESULT CALLBACK StartWindowProc(HWND, UINT, WPARAM, LPARAM); //スタートアップ
 static LRESULT CALLBACK WindowProc(HWND, UINT, WPARAM, LPARAM); //本命

 HWND SetHandle(HWND hwnd);//ウインドウハンドルを設定する
 void Create();//ここでクリティカルセクションを設定してCreateWindowを呼ぶ
}

window *m_this;

LRESULT CALLBACK window::StartWindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
 window *pThis = window::m_this;
 window::m_this = NULL;
 //ここでクリティカルセクションを取り除く
 ::SetProp(hwnd, _T("THISCLASS"), (HANDLE)pThis);
 pThis->SetHandle(hwnd);
 ::SetWindowLongPtr(hwnd, GWL_WNDPROC, (LONG)window::WindowProc);
 return window::WindowProc(hwnd, msg, wParam, lParam);
}

かなりふざけた方法だけど...
俺はこんな感じでやってる...


480:デフォルトの名無しさん
08/12/01 20:53:23
何となく、自分も昔作ったGUIを晒してみようとサンプル動かしてみたら、
リストビューを拡張して作ろうとしたらしいGridViewがいきなりバグってた。
出直してきます。orz


最新レス表示
レスジャンプ
類似スレ一覧
スレッドの検索
話題のニュース
おまかせリスト
オプション
しおりを挟む
スレッドに書込
スレッドの一覧
暇つぶし2ch