アイコン無しダイアログ

ActiveBasicでのプログラミングでわからないこと、困ったことなどがあったら、ここで質問してみましょう(質問を行う場合は、過去ログやWeb上であらかじめ問題を整理するようにしましょう☆)。
返信する
メッセージ
作成者
真紅
記事: 12
登録日時: 2005年7月20日(水) 17:59
連絡する:

アイコン無しダイアログ

#1 投稿記事 by 真紅 »

タイトルバーのアイコン無しのウィンドウって作れるのでしょうか?

WNDCLASS(EX)構造体 の hIcon・hIconSm を NULL にしたり、WM_SETICONでNULLを送るという方法ではダメでした。
何か条件や他の方法があるのでしょうか?

アイコンのない方がダイアログっぽいかなと思いまして…。
hira
記事: 203
登録日時: 2005年5月31日(火) 20:14
お住まい: 兵庫県
連絡する:

Re: アイコン無しダイアログ

#2 投稿記事 by hira »

方法としては2種類考えられます。
1つは、システムメニューをなくしてしまうことです。
RADツールをお使いなら、「システムメニュー」のチェックを外してください。
ただし、×ボタンも含めたシステムメニューが消えてしまいます。
もう1つは、プログラム中で透明のアイコンを作ってそれをウィンドウに設定することです。

コード: 全て選択

Dim hIcon As HICON
Dim AndBits[31] As Byte,XorBits[31] As Byte
FillMemory(AndBits,32,&HFF)
FillMemory(XorBits,32,&H00)
hIcon=CreateIcon(CreateStruct.hInstance,16,16,1,1,AndBits,XorBits)
SetClassLong(hMainWnd,GCL_HICONSM,hIcon) 'ウィンドウハンドルは適宜変更してください
なお、この方法を使う場合はプログラム終了時にDestroyIcon(hIcon)を呼び出す必要があります。また、本来アイコンがあるべき位置に何もなくなるので、ちょっと間が抜けた感じにはなります。
真紅
記事: 12
登録日時: 2005年7月20日(水) 17:59
連絡する:

う~ん

#3 投稿記事 by 真紅 »

やっぱりそういう方法しかないみたいですね。
クローズボタンのみってのができればいいんですけど…。

Cではリソースでダイアログを作成したりするとアイコンなしのが作れますよね。
あれはまた何か特殊だったりするのでしょうか?

とりあえずはアイコン有りでやっていこうかと思います。
有難う御座いました。
hira
記事: 203
登録日時: 2005年5月31日(火) 20:14
お住まい: 兵庫県
連絡する:

Re: う~ん

#4 投稿記事 by hira »

根本的な解決ではないかもしれませんが、RADで「拡張スタイルを設定」→「ツールウィンドウ」にチェックを入れると、アイコン無し、×ボタン付きのウィンドウが作れます。
ただ、タイトルバーの高さが半分ぐらいになるんですけどね(^^;
※そんな抜け道しか思いつかんのか、自分(爆)
真紅
記事: 12
登録日時: 2005年7月20日(水) 17:59
連絡する:

Re: う~ん

#5 投稿記事 by 真紅 »

それも考えたんですけどねー。

ツールウィンドウは別のところで使用しているので意味付け的にちょっと…。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

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

 Cなどのプログラムのダイアログはリソースとして保持していて、それを元にWinAPIのDialogBoxParam/CreateDialogParam関数で作成しています。
ABの場合はダイアログも通常のウィンドウと同じようにRegisterClassEx/CreateWindowExで作成している(そしてABプロジェクトが自動で作成するファイル内でDialogBox/CreateDialogを実装している)ためアイコンが表示されてしまいます。
ちなみにCreateDialogIndirectParam/CreateDialogIndirectParamというリソースの代わりにDLGTEMPLATE構造体を用意してこれを元にダイアログを表示するという関数もあります。
しかしこれではRADツールを使えないので非現実的です。
ABのRADがこれかリソースに対応してもらえれば一番良いのですけどね。

 こうすれば解決します、というような話でなくてすみませんが。
mako20
記事: 26
登録日時: 2005年5月31日(火) 01:10
お住まい: 岡山県
連絡する:

Re: う~ん

#7 投稿記事 by mako20 »

> 根本的な解決ではないかもしれませんが、RADで「拡張スタイルを設定」→「ツールウィンドウ」にチェックを入れると、アイコン無し、×ボタン付きのウィンドウが作れます。
> ただ、タイトルバーの高さが半分ぐらいになるんですけどね(^^;
> ※そんな抜け道しか思いつかんのか、自分(爆)

でも、ツールウィンドゥになった場合メインが対象だと、タスクバーにプログラムが出ませんから、かえって面倒ですよね
(これは、僕が体験済みやった自分で終了時面倒くさくなりました)
NoWest
記事: 264
登録日時: 2005年5月31日(火) 10:52
お住まい: 高知
連絡する:

Re: う~ん

#8 投稿記事 by NoWest »

> やっぱりそういう方法しかないみたいですね。
> クローズボタンのみってのができればいいんですけど…。
>
> Cではリソースでダイアログを作成したりするとアイコンなしのが作れますよね。
> あれはまた何か特殊だったりするのでしょうか?
>
> とりあえずはアイコン有りでやっていこうかと思います。
> 有難う御座いました。


私の意見はあんまり参考にはならないかもしれませんが
タイトルバーを自作してしまう手もありますよ。

って、こっちの方が面倒か(笑

そのやり方ですが、
多分、WM_NCPAINTメッセージをひろって
Draw~~系のAPIで描画すればいいんではないかと思います。
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

Re: う~ん

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

> でも、ツールウィンドゥになった場合メインが対象だと、タスクバーにプログラムが出ませんから、かえって面倒ですよね
通常タスクバーに表示されないウィンドウもWS_EX_APPWINDOWを付ければ表示してくれます。
具体的にはCreateイベントにこんなコードを書いてみて下さい。

コード: 全て選択

SetWindowLong(hwndMyDlg, GWL_EXSTYLE, GetWindowLong(hwndMyDlg, GWL_EXSTYLE) Or WS_EX_APPWINDOW)
真紅
記事: 12
登録日時: 2005年7月20日(水) 17:59
連絡する:

Re: う~ん

#10 投稿記事 by 真紅 »

DialogBoxIndirectParam関数を調べてみましたが、かなり大変ですね。

DLGTEMPLATE構造体の後につけなければならないという可変長配列もあまりはっきりとわからないし…。

アイコンを無しにするためにここまでやるのも疲れるので、アイコンくらいもう気にしないようにします。(逃?
Tomorrow
記事: 72
登録日時: 2005年6月04日(土) 10:09

Re: う~ん

#11 投稿記事 by Tomorrow »

> DialogBoxIndirectParam関数を調べてみましたが、かなり大変ですね。
>
> DLGTEMPLATE構造体の後につけなければならないという可変長配列もあまりはっきりとわからないし…。
この可変長配列って、たぶんコントロール(ボタンとかエディットボックスとか)だと思います。
RADで作ってくれるコントロール群はすべてCreateWindowEx関数を使用してますので、ダイアログのウィンドウだけDialogBoxIndirectParam関数で作ってしまってCallbackはRADのものを使うことができます。

追記です。
CallbackはRADのものを使えると書きましたが、ABのダイアログプロシージャとAPIのプロシージャは少し内容が違うので難しいかもしれません。
何かいい方法があればいいのですが...


自分はDLGTEMPLATE構造体を使ってウィザードを作ったことがあるので、たぶんいけると思います。
http://dbp.cool.ne.jp/patio/patio.cgi?mode=view&no=207

過去ログにDialogBoxIndirectParam関数とDLGTEMPLATE構造体を使用したダイアログ作成法が載っていたと思いますので、探してみてください。(No.1801)


P.S. 注意点というかアドバイスをすこし...

1. DLGTEMPLATE構造体はそのままのサイズでは動きません。
Dim dlg As DLGTEMPLATE などとしてもエラーになります。
上の高信期さんのサンプルでは

PTemplate = calloc(30) 'sizeof(DLGTEMPLATE) + 10

となっていますが、sizeof(DLGTEMPLATE) + sizeof(WORD)*2 + sizeof(WCHAR) = sizeof(DLGTEMPLATE) + 6 = 24バイト 以上のサイズがあれば動くみたいです。(DLGTEMPLATE構造体のサイズは実際は18バイトです。)


2.DLGTEMPLATE構造体に指定するx, cxなどのメンバはCのリソースと同じダイアログボックス単位(?うろ覚え)になってます。
そのためサイズ合わせが面倒ですので、RADツールに表示されるウィンドウサイズをコピってCreateイベントでMoveWindow, SetWindowPosあたりを呼んでサイズ変更するのが簡単かと思います。
最後に編集したユーザー Tomorrow [ 2005年7月30日(土) 19:28 ], 累計 1 回
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

RADのダイアログをDialogBoxIndirectParamで

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

なんとか表示させるところまでは漕ぎつけたましたが、それを終了させたらなぜかアプリケーション自体が終了してしまう……。
ダイアログアプリケーションならそれでも気になりませんが。
(ウィンドウMainWndにボタンを1つ置き、それを押すとダイアログDlgをDialogBoxIndirectParamで作成するという具合。ダイアログボックスにウィンドウクラスを指定したのがまずかったのかと考えてみたり)

コード: 全て選択

'dlg.sbp
Const DLGCLASS = "DlgTest"

Function InitDialog(hInstance As HINSTANCE, pszClassName As BytePtr) As Long
	Dim wcx As WNDCLASSEX
	With wcx
		.cbSize = Len(wcx)
		.style = CS_HREDRAW or CS_VREDRAW or CS_DBLCLKS
		.lpfnWndProc = AddressOf(DlgProc)
		.cbWndExtra = DLGWINDOWEXTRA
		.hInstance = hInstance
		.hCursor = LoadCursor(NULL, IDC_ARROW)
		.hbrBackground = h3DFaceBrush
		.lpszClassName = pszClassName
	End With
	RegisterClassEx(wcx)
End Function

Function DialogBoxEx(hInstance As HINSTANCE, pszClassName As BytePtr) As Long
	Dim cchClassNameA As Long, cchClassNameW As Long
	cchClassNameA = lstrlen(pszClassName)
	cchClassNameW = MultiByteToWideChar(CP_ACP, 0, pszClassName, cchClassNameA, NULL, 0)
	Dim pDialog As *DLGTEMPLATEEX
	pDialog = calloc(SizeOf(DLGTEMPLATEEX) + SizeOf(WCHAR) * (2 + cchClassNameW))
	With pDialog[0]
		.dlgVer = 1
		.signature = &hffff
		.helpID = 0
		.exStyle = WS_EX_DLGMODALFRAME Or WS_EX_WINDOWEDGE Or WS_EX_CONTROLPARENT
		.style = WS_POPUPWINDOW Or WS_VISIBLE Or WS_CLIPSIBLINGS Or DS_MODALFRAME Or WS_CAPTION
		.x = 20
		.y = 20
		.cx = 180
		.cy = 120
	End With
	Dim pDlgClassName As *WCHAR
	pDlgClassName = VarPtr(pDialog[1]) + SizeOf (WCHAR)
	MultiByteToWideChar(CP_ACP, 0, pszClassName, cchClassNameA, pDlgClassName, cchClassNameW)
 
	DialogBoxIndirectParamEx(hInstance, pDialog, NULL, NULL, 0)'AddressOf(DlgProc), 0)
	free(pDialog)
End Function

Const DLGWINDOWEXTRA = 30

TypeDef WPARAM = DWord
TypeDef LPARAM = Long
TypeDef LRESULT = LPARAM
TypeDef INT_PTR = Long
TypeDef DLGPROC = VoidPtr

Declare Function DialogBoxIndirectParamEx Lib "user32" Alias "DialogBoxIndirectParamA" (
	ByVal hInstance As HINSTANCE,
	ByVal DialogTemplate As *DLGTEMPLATEEX,
	ByVal hwndParent As HWND,
	ByVal pDialogFunc As DLGPROC,
	ByVal InitParam As LPARAM) As Long

Declare Function EndDialogAPI Lib "user32" Alias "EndDialog" (hwndDlg As HWND, nRet As Long) As Long

Type DLGTEMPLATEEX
	dlgVer As Word
	signature As Word
	helpID As DWord
	exStyle As DWord
	style As DWord
	cDlgItems As Word
	x As Integer
	y As Integer
	cx As Integer
	cy As Integer
End Type

Function DlgProc(hwnd As DWord, dwMsg As DWord, wParam As DWord, lParam As DWord) As DWord
	' TODO: この位置にウィンドウメッセージを処理するためのコードを記述します。

	If dwMsg = WM_CREATE Then
		SetWindowText(hwnd, "タイトル")
		SendMessage(hwnd, WM_INITDIALOG, 0, 0)
		DlgProc = 0
	Else
		' イベントプロシージャの呼び出しを行います。
		DlgProc = EventCall_Dlg(hwnd, dwMsg, wParam, lParam)
	End If
End Function

Sub Dlg_QueryClose(ByRef cancel As Integer)
	EndDialogAPI(hwndDlg, 0)
End Sub

コード: 全て選択

'MainWnd.sbp
Sub MainWnd_CommandButton1_Click()
	DialogBoxEx(GetWindowLong(hMainWnd, GWL_HINSTANCE), DLGCLASS)
End Sub

Sub MainWnd_Create(ByRef cs As CREATESTRUCT)
	InitDialog(cs.hInstance, DLGCLASS)
End Sub
真紅
記事: 12
登録日時: 2005年7月20日(水) 17:59
連絡する:

Re: RADのダイアログをDialogBoxIndirectParamで

#13 投稿記事 by 真紅 »

できました!!
どうもうまくいかないなと思っていたら、DialogBoxIndirectParam関数の第2引数にメモリオブジェクトハンドルを渡してしまっていました。
どっかのサイトではそんな風になってたんだけどな…。

DLGTEMPLATE構造体の後ろに付加しなければならないのは「メニュー」、「クラス名」、「タイトル名」、「フォントサイズ」、「フォント名」、「DLGITEMTEMPLATE構造体配列」らしいです。
いまいちわからないのはMSDNで書かれていたDWord境界に整列するとか何とか。
可変長配列はWord境界ともあったし、どこからどこまでをどう整列すればいいのかよくわからない…。

あとダイアログプロシージャでは処理しないメッセージをDefWindowProcに渡してはいけないそうです。
ダイアログを閉じたらアプリケーションが終了したのはこれが原因ではないでしょうか。

コード: 全て選択


Type DLGTEMPLATE
        style As DWord
        dwExtendedStyle As DWord
        cdit As Word
        x As Integer
        y As Integer
        cx As Integer
        cy As Integer
End Type

Declare Function DialogBoxIndirectParam Lib "user32" Alias "DialogBoxIndirectParamA" (hInstance As HINSTANCE,
	hDialogTemplate As *DLGTEMPLATE, hWndParent As HWND, lpDialogFunc As DWord, dwInitParam As DWord) As Long
Declare Function EndDialogAPI Lib "user32" Alias "EndDialog" (hwndDlg As HWND, nRet As Long) As Long

Function DialogBox2(hParent As HWND, x As Integer, y As Integer, cx As Integer, cy As Integer, Name As BytePtr) As Long
	Dim WideLen As Long
	Dim hMem As HGLOBAL
	Dim lpdt As *DLGTEMPLATE
	Dim lpWord As WordPtr

	WideLen = MultiByteToWideChar(CP_ACP, 1, Name, -1, 0, 0)

	hMem = GlobalAlloc(GHND, SizeOf(DLGTEMPLATE)+4+(WideLen*2))

	lpdt = GlobalLock(hMem)
	lpdt->style = WS_POPUP or WS_CAPTION or WS_SYSMENU or DS_MODALFRAME
	lpdt->x = x
	lpdt->y = y
	lpdt->cx = cx
	lpdt->cy = cy

	lpWord = lpdt+SizeOf(DLGTEMPLATE)+4
	MultiByteToWideChar(CP_ACP, 1, Name, -1, lpWord, WideLen)

	GlobalUnlock(hMem)

	DialogBoxIndirectParam(GetModuleHandle(0), lpdt, hParent, AddressOf(DialogProc), 0)

	GlobalFree(hMem)

End Function

Function DialogProc(hWnd As HWND, dwMsg As DWord, wParam As DWord, lParam As DWord) As Long
	Select Case dwMsg
        Case WM_CLOSE
			EndDialogAPI(hWnd, 0)
           	DialogProc = 1
		Case Else
			DialogProc = 0
	End Select
End Function
最後に編集したユーザー 真紅 [ 2005年7月31日(日) 17:07 ], 累計 1 回
イグトランス
記事: 899
登録日時: 2005年5月31日(火) 17:59
お住まい: 東京都
連絡する:

Re: RADのダイアログをDialogBoxIndirectParamで

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

> あとダイアログプロシージャでは処理しないメッセージをDefWindowProcに渡してはいけないそうです。
> ダイアログを閉じたらアプリケーションが終了したのはこれが原因ではないでしょうか。
私のコードはウィンドウクラスを登録して、それをDLGTEMPLATEの後ろにウィンドウクラス名を指定したんです。
なのであれはダイアログプロシージャではなく、ウィンドウプロシージャなんです。

#ところでウィンドウクラスの指定はDLGTEMPLATEでもできるのに今気づいた。
#自分としてはDLGTEMPLATEEXを使う理由はもうない。
真紅
記事: 12
登録日時: 2005年7月20日(水) 17:59
連絡する:

Re: RADのダイアログをDialogBoxIndirectParamで

#15 投稿記事 by 真紅 »

> 私のコードはウィンドウクラスを登録して、それをDLGTEMPLATEの後ろにウィンドウクラス名を指定したんです。
> なのであれはダイアログプロシージャではなく、ウィンドウプロシージャなんです。

そうなんですか。
ウィンドウクラスを指定するとダイアログプロシージャではなくなるんですね。
アプリケーションが終了してしまうのは何でだろう…。
返信する