リストビューのソートの方法

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
メッセージ
作成者
Mario2
記事: 205
登録日時: 2005年5月31日(火) 13:31
お住まい: 大阪市
連絡する:

リストビューのソートの方法

#1 投稿記事 by Mario2 »

こんにちは、早速ですが、以下の問題の解決方法がわかりません。どうすればいいのでしょうか?

ListViewにSendMessage(hList,LVM_SORTITEMS,0,0)を送ると、一番左のカラムの部分でソートが行われると思うのですが、これを2番目以降のカラムの部分でソートを行いたいのですが、0の部分を1とかに変更しても"変わらない・エラーが発生してしまい"、方法が分からず困っています。

一応質問は順番(確か"記号→012…→abc…→あいう…→漢字")ですが、もしよければ逆の方法も教えてくれるとありがたいです。(別に教えてもらえなくても結構です。)
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

Re: リストビューのソートの方法

#2 投稿記事 by 淡幻星 »

ListViewにSendMessage(hList,LVM_SORTITEMS,0,0)を送ると、一番左のカラムの部分でソートが行われると思うのですが、これを2番目以降のカラムの部分でソートを行いたいのですが、0の部分を1とかに変更しても"変わらない・エラーが発生してしまい"、方法が分からず困っています。
ソート用の関数を自前で定義する必要があるみたいですね。
私もよく知らない&現在AB環境が無いのでサンプルを作れないですが、
http://www.kumei.ne.jp/c_lang/sdk2/sdk_110.htm
が参考になるかと思います。C/C++言語の解説ページ(「猫でも分かる~」)ですが、
使っている構造体はABでも大抵定義されていると思いますので、
なんとか移植できるかと…。
で、リストビューの任意カラムでのソートは私も知りたいので、
AB用のリストビューソートライブラリにまとめてもらえると嬉しいです♪(マテ。
ははは、自分でやれって罠?(爆)。

まぁせめても、ってことで、
たぶんABには定義されて無いだろうListView_SortItemsマクロを書いてみました。

コード: 全て選択

'// commctrl.hより抜粋
'#define ListView_SortItems(hwndLV, _pfnCompare, _lPrm) \
'  (BOOL)SNDMSG((hwndLV), LVM_SORTITEMS, (WPARAM)(LPARAM)(_lPrm), \
'  (LPARAM)(PFNLVCOMPARE)(_pfnCompare))


Sub ListView_SortItems( hWnd As DWord, pfnCompare As DWord, lParamSort As Long )
	SendMessage( hWnd, LVM_SORTITEMS, lParamSort, pfnCompare )
EndSub
pfnCompareはソートを受け持つ関数へのポインタになるので
AddressOfで得る必要があります、たぶん。
その関数の組み方しだいで、昇順やら降順やら好きなようにソートできそうですね。

もう一つ。
たぶんABでは定義されていない(少なくともVer.3.13では)リストビュー関連の構造体やらマクロなど。
Mario2
記事: 205
登録日時: 2005年5月31日(火) 13:31
お住まい: 大阪市
連絡する:

Re: リストビューのソートの方法

#3 投稿記事 by Mario2 »

淡幻星さん、回答ありがとうございます。
URL参考にさせてもらいますが、自分では解読が困難なので、もう少し他の方の回答を待ってみます。
(実はサンプルが欲しかったりするだけ)(←こういうユーザは嫌われそうな・・・(^^;;;;))
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

Re: リストビューのソートの方法

#4 投稿記事 by 淡幻星 »

(実はサンプルが欲しかったりするだけ)(←こういうユーザは嫌われそうな・・・(^^;;;;))
少なくとも、好まれはしないと思います。
・・・が、「サンプルが欲しいんです!」って気持ちはよ~く分かります^^;
なので、私は悪いとは思いません。
やっぱ、サンプルがなくちゃ分かりませんよね~┐(´ー`)┌


さて。
リストビューの任意のカラムを昇順/降順に並び替える関数を作ってみました。
ListView_SortItems_UpDown()です。
ただし、テストしてませんので(現在AB環境にありません故^^;)
エラーしたらごめんなさい。
なお、これを利用するためには、アイテムをリストボックスに追加する際に、
LV_COLUMN構造体のmaskメンバにLVIF_PARAMを指定しておく必要があるみたいです。 BackSearchABのysamaさんのログ(No.8905)を参考にさせていただきました。
グローバル変数を二つほど使ってます。
「猫でも分かる~」なども見るところでは、リストビューのソートでは、
リストビューのハンドルと、昇順/降順/ソートされてないの管理を
グローバル変数で渡すのが慣例みたいですね。
たまたまなのか、何か意味があるのかは分かりません。
個人的に、グローバルは極力使いたくないのですが・・・クラス化するしかないのかな?
それから、LV_FINDINFO構造体の定義はあっているか自信がありません^^;
→修正→追記:合ってました。アンダーバー除いた形で、ABでも定義されてました(爆)。


ふぃ。いつものように蛇足。
コールバック関数って要するに何なのか未だに分からない~┐(´ー`)┌
Mario2
記事: 205
登録日時: 2005年5月31日(火) 13:31
お住まい: 大阪市
連絡する:

Re: リストビューのソートの方法

#5 投稿記事 by Mario2 »

(実はサンプルが欲しかったりするだけ)(←こういうユーザは嫌われそうな・・・(^^;;;;))
> 少なくとも、好まれはしないと思います。
> ・・・が、「サンプルが欲しいんです!」って気持ちはよ~く分かります^^;
> なので、私は悪いとは思いません。
> やっぱ、サンプルがなくちゃ分かりませんよね~┐(´ー`)┌
やっぱりですよね。でも、そこからの改変は自分でやらないと、自分の力にはなりませんからね。あくまで動作するサンプルが欲しいのですよ。

> ふぃ。いつものように蛇足。
> コールバック関数って要するに何なのか未だに分からない~┐(´ー`)┌
英語にするとCall Back、呼び戻す?ってこのなのかな?自分もコールバック関数は良く分かりません。(^^;;
Mario2
記事: 205
登録日時: 2005年5月31日(火) 13:31
お住まい: 大阪市
連絡する:

Re: リストビューのソートの方法

#6 投稿記事 by Mario2 »

淡幻星さん、どうもありがとうございます。
提供していただいたサンプルを元に、一部を修正したら動作しました。
どうもありがとうございました。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

Re: リストビューのソートの方法

#7 投稿記事 by イグトランス »

> 英語にするとCall Back、呼び戻す?ってこのなのかな?

そのとおりです。WinAPIにおけるWindowsのような,
機能を提供する側が利用する側を呼び出すことをコールバックと呼び,
コールバックされる関数をコールバック関数というのです。
Mario2
記事: 205
登録日時: 2005年5月31日(火) 13:31
お住まい: 大阪市
連絡する:

Re: リストビューのソートの方法

#8 投稿記事 by Mario2 »

> > 英語にするとCall Back、呼び戻す?ってこのなのかな?
>
> そのとおりです。WinAPIにおけるWindowsのような,
> 機能を提供する側が利用する側を呼び出すことをコールバックと呼び,
> コールバックされる関数をコールバック関数というのです。

そういう意味だったんですか。イグトランスさん、回答ありがとうございます。
(あと、"このなのかな?"ってなってますが、もちろん"ことなのかな?"の間違いです(汗爆))
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

コールバック関数とは?

#9 投稿記事 by 淡幻星 »

イグトランスさん さんが書きました:そのとおりです。WinAPIにおけるWindowsのような,
機能を提供する側が利用する側を呼び出すことをコールバックと呼び,
コールバックされる関数をコールバック関数というのです。
???
つまり、コード上で明示的に呼び出される関数ではなくて、
いったんWindowsのような機能提供側(「カーネル」で良いんでしょうか?)に
処理を投げた(DispatchMessageとか)後に、提供側から決まった形(引数etc)で
呼び出される関数のことを、「制御が呼び出し側に戻された=コールバック」という意味で
コールバック関数と呼ぶ、という理解で合ってますでしょうか?


関連として、以下の理解は合っておりますでしょうか?
1) コールバック関数は、仕様としてコンパイル時点で関数アドレスが
  存在していなければならない(提供側が呼び出す故?)。
2) 呼び出しの時点までアドレスが存在しない関数を仮想関数と呼ぶ。
3) クラスはオブジェクトが生成されるまでは実体が無い。
  したがって、そのメソッドはコンパイル時は仮想関数である。
  (故に、メソッドにstatic以外ではコールバック関数を持てない。)
4) C/C++でいうところの WINAPI 識別子(で良いのかな?)が
  付いているものは、コールバック関数である。
5) 現在、ABにはstatic識別子はない。

話が脱線してしまいすいませんが、答えていただければ幸いです。
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

Re: コールバック関数とは?

#10 投稿記事 by NoWest »

> つまり、コード上で明示的に呼び出される関数ではなくて、
> いったんWindowsのような機能提供側(「カーネル」で良いんでしょうか?)に
> 処理を投げた(DispatchMessageとか)後に、提供側から決まった形(引数etc)で
> 呼び出される関数のことを、「制御が呼び出し側に戻された=コールバック」という意味で
> コールバック関数と呼ぶ、という理解で合ってますでしょうか?
OSから送られてきたメッセージをGetMessage関数で捕まえて、DispatchMeesage関数を呼び出した時に、適切なウィンドウにメッセージが送信されます。これを受けてウィンドウ(OS)はコールバック関数を呼び出します。

ようするに、OSさんがプログラマに

「こんなメッセージが送られてきたんですけど、このウィンドウはどんなふうに動くんですか?」

と、コールバック関数を介して、聞きに来ているんですね。

> 関連として、以下の理解は合っておりますでしょうか?
> 1) コールバック関数は、仕様としてコンパイル時点で関数アドレスが
>   存在していなければならない(提供側が呼び出す故?)。
コンパイル時でなくても実行時にアドレスが存在していれば問題ないです。

例えば、DLL内にコールバック関数を収めておき、呼び出す関数をGetProcAddress関数なんぞで切り替えてやれば、プラグインなんかも作れます。
> 2) 呼び出しの時点までアドレスが存在しない関数を仮想関数と呼ぶ。
なんともいえません。
開発環境が違ってくると仮想関数も違ってきます。
今の現在(AB4)のところABでは厳密な意味での仮想関数は使えません。
(所謂、VCでいうところのvirtual指定は使えない)
> 3) クラスはオブジェクトが生成されるまでは実体が無い。
>   したがって、そのメソッドはコンパイル時は仮想関数である。
>   (故に、メソッドにstatic以外ではコールバック関数を持てない。)
基本的にはそうです。

SetProp関数だったかなんかで、クラスのメソッドにコールバック関数を含めることが出来たような気がします。

追記2005/12/22/23:10ごろ
SetProp関数が使えるのはウィンドウプロシージャだけのようです。
でも、グローバルアトムとか使ってデータの共有化を行えばVatPtr(This)ポインタとかをコールバック関数に引き渡すことが出来そうです。

> 4) C/C++でいうところの WINAPI 識別子(で良いのかな?)が
>   付いているものは、コールバック関数である。
とくにそう決まっているわけではありません。
WINAPIというのは関数がstdcall形式で定義されていることを表しています。
標準APIではありませんがコールバック関数の中にはごくまれにcdecl形式のものも存在します。
> 5) 現在、ABにはstatic識別子はない。
そうです。ぜひ欲しいですよね。



私も(笑
話はそれますが、

コールバック関数は自分で作成した関数でも使えますよ。

下はファイル名を列挙するサンプルです。

コード: 全て選択

TypeDef ENUMFILEPROC = *Function(ByRef lpwfd As WIN32_FIND_DATA) As Long

Function EnumFile(lpFileName As *Char, lpfnCallback As ENUMFILEPROC) As Long
	If lpfnCallback=NULL Then
		EnumFile = FALSE
		Exit Function
	End If

	Dim hFind As HANDLE
	Dim w32fd As WIN32_FIND_DATA
	hFind=FindFirstFile(lpFileName,w32fd)
	If hFind=INVALID_HANDLE_VALUE Then
		EnumFile = FALSE
		Exit Function
	End If

	While lpfnCallback(w32fd)=0
		If FindNextFile(hFind,w32fd)=FALSE Then Exit While
	Wend
	FindClose(hFind)
	EnumFile = TRUE
End Function

コード: 全て選択

Function test(ByRef wfd As WIN32_FIND_DATA) As Long
	If InStr(1,MakeStr(wfd.cFileName),"WINDOWS") Then
		MessageBox(NULL,wfd.cFileName,"test",0)
		test=1
	End If
End Function

EnumFile("C:\*.*",AddressOf(test))
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

Re: コールバック関数とは?

#11 投稿記事 by イグトランス »

つまり、コード上で明示的に呼び出される関数ではなくて、
いったんWindowsのような機能提供側(「カーネル」で良いんでしょうか?)に
処理を投げた(DispatchMessageとか)後に、提供側から決まった形(引数etc)で
呼び出される関数のことを、「制御が呼び出し側に戻された=コールバック」という意味で
コールバック関数と呼ぶ、という理解で合ってますでしょうか?
そういうことになります。(ただ全てがカーネルとは限りませんが)
1) コールバック関数は、仕様としてコンパイル時点で関数アドレスが
  存在していなければならない(提供側が呼び出す故?)。
そもそもクラスのメンバ関数を含め全ての関数はメモリ上に存在する以上,どんな関数にも必ずアドレスがあります。
(インライン展開されてしまえば別ですが)
と書きましたがNoWestさんのDLLというのは見過ごしていました。
ただそれでも依然DLLのコンパイル時に存在するということになります。
2) 呼び出しの時点までアドレスが存在しない関数を仮想関数と呼ぶ。
いいえ。仮想関数と言えども上記1の理由で実体へのアドレスは存在します。
呼び出すときまでアドレスが存在しないのではなく,呼び出すときまでわからないというだけです。
どういうことかというと仮想関数へのポインタが収められた表(VTBL)が
オブジェクトの中に埋め込まれているので,
これを参照してみないことにはどこの関数を呼び出してよいかわからないからです。
逆に言えば対象となるオブジェクトが定まれば呼び出す仮想関数の実体も決まるということです。
これはAB4のVirtual関数にも当てはまることです。
3) クラスはオブジェクトが生成されるまでは実体が無い。
  したがって、そのメソッドはコンパイル時は仮想関数である。
概ねいいえです。
どういうことかというとオブジェクトが生成されるまでクラスの実体がないというのは概念上間違っていないのですが,
現実にはメンバ関数もその他と同じように機械語になるという点において,結局はその他の関数と何も変りません。
仮想関数か否かはあくまで仮想関数だという指定がなされているかどうかによります。
(少なくともABやC++/C#などの場合はそうです。その他の方法で仮想関数かどうか決める言語もあります)
  (故に、メソッドにstatic以外ではコールバック関数を持てない。)
これは前述の通りメンバ関数が実際には単なる関数と変らないことに起因します。
メンバ関数は宣言に書いた引数以外にオブジェクトへのポインタを引数に取ることからそのままでは引数の数が合わず,
さらに呼び出し規約も合わないためということもあります。
逆にこれらの問題を解決すればできるということでもあります。COMオブジェクトが良い例です。
WinAPIのコールバック関数でも大抵余計な引数を受け渡しできるようになっています。
これを使えばなんとかなります。
4) C/C++でいうところの WINAPI 識別子(で良いのかな?)が
  付いているものは、コールバック関数である。
大抵そうです。
厳密に言えばコールバック関数でなくともWINAPIをつけられるのです。あまり意味はありませんが。
逆に言えばお互いにきちんと決めて統一してあればどのような関数でもコールバック関数になれます。
とは言えWindowsプログラムではWINAPIが一般的ですけどね。
5) 現在、ABにはstatic識別子はない。
これはたしかにそうです。明白ですね。
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

Re: コールバック関数とは?≫NoWestさん

#12 投稿記事 by 淡幻星 »

NoWestさん、ありがとうございます。

ようするに、OSさんがプログラマに
「こんなメッセージが送られてきたんですけど、このウィンドウはどんなふうに動くんですか?」
と、コールバック関数を介して、聞きに来ているんですね。
すいません。こっちの説明は分かったんですが、
下はファイル名を列挙するサンプルです。
でよく分からなくなりました。
普通に関数を呼んでいるだけじゃないかと。
ん~、もしかして「コールバック関数」とは、
適切なウィンドウにメッセージが送信されます。
のように、送り先を選択できる関数ってことですか?
たとえば、サンプルであれば
While lpfnCallback(w32fd)=0
で呼び出される関数は、Function EnumFile() の引数次第で変更できますよね。
でもこの機能は、コールバック関数ゆえの機能というより
関数ポインタゆえの機能な気がしますが・・・(^^;)
それとも、関数ポインタを通して呼ばれるものを
「コールバック関数」と呼ぶのでしょうか?
でも、だとするとCreateThread()で呼ばれるサブスレッドも
コールバック関数になってしまいますね。
でもあれはコールバック関数ではないらしい・・・。うーん難しい(@_@)

開発環境が違ってくると仮想関数も違ってきます。
なるほど。
「仮想関数」が指すものは、開発環境次第なのですね。
基本的にはそうです

SetProp関数だったかなんかで、クラスのメソッドにコールバック関数を含めることが出来たような気がします。

追記2005/12/22/23:10ごろ
SetProp関数が使えるのはウィンドウプロシージャだけのようです。
でも、グローバルアトムとか使ってデータの共有化を行えばVatPtr(This)ポインタとかをコールバック関数に引き渡すことが出来そうです。
調べていただいてありがとうございます。・・・が、そっちは知ってました(^^;)
「コールバック関数を持てない」と書いたのは、直には持てない、という意味でした。
誤解を招く発言でしたね。失礼^^;
グローバルアトムを使うほかにも、
一つ目の参考サイトより抜粋 さんが書きました:コールバック関数の中には、引数の中に「アプリケーション定義の変数を渡す void ポインタ」のパラメータがあるものがあります。このようなコールバック関数の場合は、そのパラメータにクラスのポインタを渡してやり、コールバック関数内でそのクラスの型にキャストして、メンバ変数や関数にアクセスすることでこの問題を解決できます。
といった方法があるみたいですね。
肝心のウィンドウプロシージャの場合は、SetProp関数を使うのが
一般的(MFCのCWndクラスもそれ?)みたいですが、
SetProp()はアトム(=文字列)を使っているため若干重いらしく、
それを嫌う人は
「ウィンドウに関連付けられたアプリケーション定義の 32 ビット値」
を利用してstaticメソッド→目的のメソッド、と呼び出すことで、
コールバック関数をクラスのメソッドに含めているみたいです。
(蛇足へ続く^^;)
参考http://techtips.belution.com/ja/vc/0009/
  http://forums.belution.com/ja/vc/000/047/79s.shtml


WINAPIというのは関数がstdcall形式で定義されていることを表しています。
あ、そっちでしたか。
なんのための識別子なのか、ひとつスッキリしました♪
Quote:
> 5) 現在、ABにはstatic識別子はない。
そうです。ぜひ欲しいですよね。
えぇ。ぜひ欲しいですねw


以下、いつものように蛇足です(笑)。
SetProp()を使わずに、クラスのメソッドに
ウィンドウプロシージャを含める方法です。
***
CreateWindow()の第11引数(~Ex()なら第12引数)のlpParm As VoidPtrに
VatPtr(This)を渡す、つまり窓に関連付けられた32bit値として
呼び出しもとのクラスのポインタを保持して、
staticなメソッドで受けた後にGetWindowLong( hWnd, GWL_USERDATA )
で取り出してstaticでないメソッドを呼び出します。
***
もちろん、GWL_USERDATAを後で使えないのが欠点。
しかし、窓をクラス化してしまったのなら、使う場面は無いように
思うので、たぶん不具合はないかと(へヴィーなものを書く人は別^^;)。
C++ですが、サンプルは・・・と最初は載せたのですが、
あくまでも「蛇足」の話題ですし、ABのフォーラムなので止めておきます^^;。
削除しました(12月23日の2時ごろ)
最後に編集したユーザー 淡幻星 [ 2005年12月23日(金) 02:03 ], 累計 2 回
淡幻星
記事: 183
登録日時: 2005年7月19日(火) 07:02
お住まい: 宮城県
連絡する:

Re: コールバック関数とは?≫イグトランスさん

#13 投稿記事 by 淡幻星 »

≫イグトランスさん
おっと。
レスを書いているうちに、投稿されてましたか。
失礼。もうすこし読んでから、またレスします。
今一通り流し読みしただけでは理解できませんでした^^;
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

Re: NoWestさんからの回答

#14 投稿記事 by NoWest »

淡幻星 さんが書きました:> ん~、もしかして「コールバック関数」とは、
>
適切なウィンドウにメッセージが送信されます。
のように、
送り先を選択できる関数ってことですか?
いえいえ、その説明はコールバック関数(ここではウィンドウプロシージャ)が呼び出されるまでを説明したものです。

もう一度全体の流れを詳しく順に書きます。

1.アプリケーションが実行されるとウィンドウを作成しGetMessage関数を含むループが回り始める。
追記:回るとはいってもメッセージが無い状態では実際にはGetMessage関数で待機状態となっています。

2.OSからウィンドウが操作されたりキーが押されたことをメッセージとして
実行中のアプリケーションのスレッドへ送信

3.GetMessage関数がメッセージを受信すると、DispatchMessage関数を呼び出し、アプリケーションが作成したウィンドウにメッセージが送信される。

4.メッセージを受信したウィンドウはウィンドウクラスに関連付けられているウィンドウプロシージャつまりコールバック関数を呼び出す。


コールバック関数が実行されるのは最後の4.のプロセスです。

淡幻星 さんが書きました:> たとえば、サンプルであれば
> While lpfnCallback(w32fd)=0
> で呼び出される関数は、Function EnumFile() の引数次第で変更できますよね。
> でもこの機能は、コールバック関数ゆえの機能というより
> 関数ポインタゆえの機能な気がしますが・・・(^^;)
コールバック関数=関数ポインタ
というのは正しくは無いですが、間違いでもありません。

コールバック関数とはシステム内部では関数ポインタの形で扱われます。
ウィンドウプロシージャもウィンドウクラスを定義する際にはAddressOfを使用して関数ポインタを登録します。

上でも書きましたが、ウィンドウは自分のウィンドウクラスに登録されているコールバック関数への関数ポインタを頼りにウィンドウプロシージャを呼び出しているだけです。

淡幻星 さんが書きました:> それとも、関数ポインタを通して呼ばれるものを
> 「コールバック関数」と呼ぶのでしょうか?
> でも、だとするとCreateThread()で呼ばれるサブスレッドも
> コールバック関数になってしまいますね。
> でもあれはコールバック関数ではないらしい・・・。うーん難しい(@_@)
「コールバック」という言葉には「電話をかけ直す」という意味があります。
つまり、コールバックという仕組みは、「ある処理を実行する際に、その一部を外部で後から追加できるようにしたもの」あるいは「ある処理が確実に実行されたことを通知するもの」だと定義できます。

コールバックというのは何も「関数」だけではないんです。
コールバックスレッドコールバックタスクコールバックイベントなんてのもあります。


あまり、実感は湧かないかも知れませんが、
GetMessage関数を使ったループは実はコールバックスレッドなんですよ。

OSが「あなたのスレッドに、こんなウィンドウハンドルのウィンドウにこんなウィンドウメッセージが送られてきていますよ。」
と通知してきたら、プログラマはそのメッセージをウィンドウに送信するかしないかを決定できるんです。
Windowsのシステムの特定の処理に対して、プログラマが選択的に処理を組むことができる仕組みがコールバックです。もちろんコールバックと言う仕組みはWindowsが提供しているものだけに限ったものではありませんし、ウィンドウ制御だけに使うわけではありません。

コールバックを使用するものには、
例えばWAVE関連のAPIや、MIDIストリーミング、OpenGL(Glut)の描画ルーチン、ウィンドウの検索、ディスプレイの列挙、GDIオブジェクトの列挙、フォントの列挙など多種多様です。


かなり話題がそれましたので
分からないことがあれば別のスレッドにでもしてください。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

Re: コールバック関数とは?≫NoWestさん

#15 投稿記事 by イグトランス »

淡幻星さん さんが書きました:でも、だとするとCreateThread()で呼ばれるサブスレッドも
コールバック関数になってしまいますね。
でもあれはコールバック関数ではないらしい・・・。うーん難しい(@_@)
いや,CreateThreadの場合も形としてはコールバック関数です。
ただスレッドを作るという機能が強調されるので,
特にコールバックとは言われないことが多いだけですよ。
淡幻星さん さんが書きました:SetProp()はアトム(=文字列)を使っているため若干重いらしく、
それを嫌う人は
「ウィンドウに関連付けられたアプリケーション定義の 32 ビット値」
を利用してstaticメソッド→目的のメソッド、と呼び出すことで、
コールバック関数をクラスのメソッドに含めているみたいです。
SetPropに文字列ではなくアトムを使った場合は,SetWindowLongを使った場合とほぼ同じ速度だという計測結果があります。
http://hilbert.elcom.nitech.ac.jp/~taki/program.html
ある程度参考になるのではないでしょうか。
淡幻星さん さんが書きました:もちろん、GWL_USERDATAを後で使えないのが欠点。
これはSet/GetWindowLongでGWL_USERDATA以外を使えばいいのです。
SetClassLongでGCL_CBWNDEXTRAを指定するとGWL_USERDATAとは別に
ウィンドウ毎のメモリ領域が用意されます。
(本来はRegisterClassExで指定するのでしょうがRADツールが隠してしまっているので)
これはABのヘルプのSet/GetWindowLongの項目にある,
「拡張ウィンドウメモリからデータを取得するときは、0 から始まるオフセットをバイト単位で指定します。」
というものに該当するものです。GWL_USERDATAと同じ感覚で使えます。
返信する