So-net無料ブログ作成
検索選択

モーダルで表示したフォームをタスクバーに表示する TaskBarList.Lib [program]

VB6ではモーダルで表示したフォームはタスクバーに表示されません。

外部プログラムから起動されるプログラムをVBで作成する場合、
引数を処理する関係で、
スタートアップをMain関数にして、フォームをモーダルで表示することがあります。

以前、その様なコーディングを行ったところ、
フォームが表示されているのに、タスクバーに表示されない事が問題になりました。
フォームが別のプログラムのフォームの裏に隠れてしまうと、
タスクバーで切り替えできないからです。

このような事例は多かったはずなのですが、今まで対応した記録がなく、
私が対応方法を調べる事になりました。

比較的容易にITaskBarListインターフェイスを使用すれば実現できる事が分かり、
そのためのタイプライブラリがネットで無償公開されている事が分かりましたが、
仕事で使用するには、由来がはっきりしないモジュールは使用できません。

そこで、タイプライブラリを作成することにしました。

海外のサイトで公開されていたODL関係のサンプルソースを参考に、
ソースを作成したのだったと思います。
当時はODL言語についても調べたのですが、
時間がたっていることと、
何しろ突貫工事だったので、記憶もあいまいで、記録もまとまっていません。

それでも、今のところ動いています。

もし誤り等がありましたら、ご指摘ください。



TaskBarList.odl(ソース)
タイプライブラリ自身のUIDをGUIDGen.EXE等で作成して設定してください。

[
   uuid(タイプライブラリ自身のUID),
   helpstring("LibTaskbarList"),
   version(1.00)
]
library LibTaskbarList {
	importlib("stdole2.tlb");
	
	interface ITaskbarList;

	
	[
		odl,
		uuid(56FDF342-FD6D-11d0-958A-006097C9A090),
		helpstring("ITaskbarList interface")
	]
	
	interface ITaskbarList : IUnknown {
		
		HRESULT HrInit();
		
		HRESULT AddTab([in] LONG hwnd);
		
		HRESULT DeleteTab([in] LONG hwnd);
		
		HRESULT ActivateTab([in] LONG hwnd);
		
		HRESULT SetActiveAlt([in] LONG hwnd);
	};
	
	[
		uuid(56FDF344-FD6D-11D0-958A-006097C9A090),
		helpstring("TaskbarList class")
	]
		coclass TaskbarList {
		[default] interface ITaskbarList;
	};

};


MKtyplib.exeでタイプライブラリを作成します。
MKtyplib.exeはVisual StudioのVCフォルダのBinフォルダにあるはずです。

MKTYPLIB.EXE TaskBarList.odl /nocpp /tlb TaskBarList.tlb


VBからTaskBarList.tlbを参照設定すれば使用できます。

リファレンス
HrInit()
	クラスの初期化を行う。
	TaskBarListクラスのインスタンスを作成した後、一度だけ行ってください。

AddTab(hWnd)
	hWnd・・・ウインドウハンドル
	指定したウインドウをタスクバーに追加する

DeleteTab(hWnd)	
	hWnd・・・ウインドウハンドル
	指定したウインドウをタスクバーから削除する

ActivateTab(hWnd)	
	hWnd・・・ウインドウハンドル
	指定したウインドウをアクティブにするタブもアクティブになる




サンプル
'--Module1
Sub Main()
	Dim frm1 as Form1
	Set frm1 = New Form1
	frm1.Show vbModel
End Sub

'--Form1
Private TaskBarList As TaskBarList

Private Sub Form_Load()
	Set TaskBarList = New TaskBarList
	'初期化
	TaskBarList.HrInit
	'タスクバーに追加
	TaskBarList.AddTab Me.hWnd
End Sub

Private Sub Form_QueryUnload(Cancel As Integer, UnloadMode As Integer)
    	'タスクバーから削除
	TaskBarList.DeleteTab Me.hWnd
	Set TaskBarList = Nothing
End Sub


※プログラム関係の記事がたまったら別ブログにしようと思います。

DataGridViewのコンボボックスをDELキーでクリアしたい [program]

カスタマイズしていたパッケージソフトのコントールが不具合で使用できず、
急遽標準のグリッドに置き換えることになった。
なるべく動作を合わせなくてはならない。

「コンボボックス表示されるセルの値をDELキーでクリアする」という仕様で行き詰った。

DataGridViewのEditingControlShowingイベントでDataGridViewComboBoxEditingControlを取得して、
そのKeyDownイベントでSelectedIndex = -1を設定するところまでは、すぐに思いついた。

しかし、すでにセルに値が設定されていると、
フォーカスが離れた後に元の値に戻ってしまうのだ。
これには頭を抱えてしまった。

結局、編集終了後のCellEndEditイベントで、
SelectedIndex = -1ならセルに空文字を設定することにした。
その後DataGridViewComboBoxEditingControlへの参照をクリアしてしまうので、
CellEndEditイベントでは、DataGridViewComboBoxEditingControlへの参照が存在するかどうかをチェックすることにした。

サンプルはVB2008Exp、グリッドはアンバウンドです。
仕事でExpて悲しいでしょ・・・

''' DataGridViewに表示されるDataGridViewComboBox
Private WithEvents DataGridViewComboBox As DataGridViewComboBoxEditingControl = Nothing

'''カラムの列挙
Private Enum GridCol As Integer
	Text = 0
	Value = 1
End Enum

''' DataGridViewにDataGridViewComboBoxが表示されたら取得する
Private Sub DataGridView1_EditingControlShowing(ByVal sender As Object, _
	ByVal e As System.Windows.Forms.DataGridViewEditingControlShowingEventArgs) _
	Handles DataGridView1.EditingControlShowing
	
	If TypeOf e.Control Is DataGridViewComboBoxEditingControl Then
		Dim DGView As DataGridView = DirectCast(sender, DataGridView)

		Me.DataGridViewComboBox = _
		DirectCast(e.Control,DataGridViewComboBoxEditingControl)
	End If
End Sub


''' DataGridViewComboBoxのイベントでDELキーを受け、リストをクリアする
Private Sub DataGridViewComboBox_KeyDown(ByVal sender As Object, _
	ByVal e As System.Windows.Forms.KeyEventArgs) _
	Handles DataGridViewComboBox.KeyDown
	
	If e.Alt = False AndAlso e.Control = False AndAlso e.KeyCode = Keys.Delete Then
		Dim DGVComboBox As DataGridViewComboBoxEditingControl = _
		DirectCast(sender, DataGridViewComboBoxEditingControl)
		DGVComboBox.SelectedIndex = -1
	End If
End Sub


'''編集終了時にリストが選択されていなければ、
'''セルに空文字を入れて、 DataGridViewComboBoxを初期化
Private Sub DataGridView1_CellEndEdit(ByVal sender As Object, _
	ByVal e As System.Windows.Forms.DataGridViewCellEventArgs) _
	Handles DataGridView1.CellEndEdit
	
	If Not Nothing Is Me.DataGridViewComboBox Then
		If Me.DataGridViewComboBox.SelectedIndex = -1 Then
			Dim DGView As DataGridView = _
			DirectCast(sender, DataGridView)
			DGView.Rows(e.RowIndex).Cells(GridCol.Value).Value = ""
		End If

		Me.DataGridViewComboBox = Nothing
	End If
End Sub


※プログラム関係の記事がたまったら別ブログにしようと思います。