リストボックスに横スクロールバーを付けたい

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
wasawasa
記事: 94
登録日時: 10年前

リストボックスに横スクロールバーを付けたい

#1

投稿記事 by wasawasa » 10年前

こんにちは、いつもお世話になっています。
リストボックスhListに横スクロールバーを付けたいと思ってウィンドウスタイルにWS_HSCROLLを追加したところ、横スクロールバーは表示されませんでした。
これについて調べたところ
SendMessage(hList,LB_SETHORIZONTALEXTENT,x,0);
という風にxピクセル分のスクロール幅を用意させるメッセージをリストボックスに送る必要があると分かったので、文字列の幅を取得する関数を探したところ
GetTextExtentPoint32(HDC hdc,LPCTSTR lpString,int cbString,LPSIZE lpSize);
というデバイスコンテキストhdcと文字列lpstringと文字数cbStringから文字列の幅を取得してlpSizeに格納する関数を見つけました。
デバイスコンテキストは
hdc=GetWindowDC(hList);
文字数は
SendMessage(hList, LB_GETTEXTLEN ,lpString,0);
で求められるので、リストボックスに文字列を書き込む記述に文字列の長さを取得する記述を差し込んで下記のように書いて実行したところ、「Run-Time Check Failure #3 - The variable 'hStrSize' is being used without being initialized.」というエラーが発生してしまいました。
これは初期化されていない状態で数値として使用しようとした事に対する警告のメッセージのようであり、31行目でストップしていたのでここで数値として参照する事になったようですが、31行目ではhStrSizeを数値として参照しているのではなく、文字列のサイズを格納する変数として参照しているだけなので初期化が求められる意味が分かりません。
一体何故警告されたのでしょうか?

コード:

//変数宣言・定義
LPTSTR Str[] = {
	L"hogehogehogehogehogehogehogehoge" ,
	L"hogehogehoge" ,
	L"hogehogehogehogehogehogehogehoge" ,
	L"hogehogehoge" ,
	L"hogehogehogehogehogehogehogehoge" ,
	L"hogehogehoge" ,
	L"/None"
};
WCHAR num[256]={0};
int i;
LPSIZE hStrSize;
int StrLength=0;
//--記述内容---------------------------------------
hList = CreateWindowEx(
	NULL,
        L"LISTBOX" ,NULL , 
	WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL | WS_HSCROLL , 
	x ,y ,	width ,height,hMAGroup ,
	(HMENU)ID ,hInst , NULL);
for(i=0;i<20;i++){
	if(wcscmp(Str[i],L"/None")!=0){
		_itow_s(i+1,num,10);
		wcscat(num,L":");
		wcscat(num,Str[i]);
		GetTextExtentPoint32(
			GetWindowDC(hList),
			num,
			wcslen(num),
			hStrSize);
		if(hStrSize->cx>StrLength){
                        StrLength=hStrSize->cx;
                }
		SendMessage(hList , LB_INSERTSTRING , i , (LPARAM)num);
	}
	else{break;}
}
SendMessage(hMaterialList,LB_SETHORIZONTALEXTENT,StrLength,0);

アバター
milfeulle
記事: 47
登録日時: 10年前
住所: マリーランド
連絡を取る:

Re: リストボックスに横スクロールバーを付けたい

#2

投稿記事 by milfeulle » 10年前

警告の内容はhStrSizeが初期化せずに使われていることですが、hStrSizeの変数に着目されると、
LPSIZE hStrSize;
と宣言されているようです。これがいけません。

というのも、C/C++では、ポインタが必要としているときは、ある実態があって、その実態のポインタを渡すことが鉄則だからです! ポインタだけを宣言しても、そのポインタはどこを指しているのか不明です。だから、渡すときは
1. ほぼ確実に指していると考えれられるポインタ
2. &演算子で実態のアドレスをちょくに渡す
のどちらかを用います。

Windows APIはシステムハンガリアン記法を採用しています。(私は大嫌いですw) LPSIZEは、SIZEという方の名前に加えて、L=Long, P=Pointerとして、Long型でかつ*(ポインタ)という意味合いなのですが、たいていポインタにはLPとついています。ですから、知らずのうちにポインタとして宣言されているかもしれません。

とりあえず、(本題であろう)スクロールなど無関係の問題を指摘させていただきました。

なお、以下は同じエラーを再現するであろう最小の例です。

コード:

void func(int* p) {
	*p = 10;
}

int main(void) {
	int x; // これは実態
	int* p; // これはポインタ
	int* p_x; // これもポインタ

	p = &x;

	func(&x); // 実態のx
	func(p); // ほぼ確実なp
	func(p_x); // 実態のないp_x。エラー!!
}
ζ*'ヮ')ζプログラミングはみんなで奏でるシンフォニー

wasawasa
記事: 94
登録日時: 10年前

Re: リストボックスに横スクロールバーを付けたい

#3

投稿記事 by wasawasa » 10年前

>>milfeulleさん
返信ありがとうございます。

hStrSizeはSIZE型で宣言するとコンパイルの時点で
「'GetTextExtentPoint32W' : 4 番目の引数を 'SIZE' から 'LPSIZE' に変換できません。(新しい機能 ; ヘルプを参照)」
というエラーが出てしまうのでLPSIZE型に変更したのですが、SIZE型で変数を宣言した場合このエラーをどう解決すればいいのでしょうか?
引数に指定するときに(LPSIZE)hStrSizeと指定しても「'SIZE' から 'LPSIZE' に変換できません。」と出てしまうので他に方法が思いつきません。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: リストボックスに横スクロールバーを付けたい

#4

投稿記事 by みけCAT » 10年前

milfeulle様の回答のコードの12行目の方法を用いればいいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

naohiro19
記事: 256
登録日時: 13年前
住所: 愛知県

Re: リストボックスに横スクロールバーを付けたい

#5

投稿記事 by naohiro19 » 10年前

GetTextExtentPoint32 関数
LPSIZE lpSize はSIZE構造体のポインタです。
ポインタですのでGetTextExtentPoint32に渡すさいに&で渡さなければなりません。
文字列の幅(WisdomSoft)

wasawasa
記事: 94
登録日時: 10年前

Re: リストボックスに横スクロールバーを付けたい

#6

投稿記事 by wasawasa » 10年前

>>みけCATさん
>>naohiro19
ポインタという点を見落としていたみたいです。
&hStrSizeと指定して実行したらできました。ありがとうございます。

閉鎖

“C言語何でも質問掲示板” へ戻る