ホーム » 検索結果: オーナー

検索結果: オーナー

2024年5月
 1234
567891011
12131415161718
19202122232425
262728293031  

カテゴリー

アーカイブ

ブログ統計情報

  • 80,817 アクセス



CListBox などのオーナードロー

リストスクロール時,動作が逆に見える現象の調査のため調べたこと.


WinCore.cpp CWnd::OnMeasureItem での CtlType の値

/*
 * Owner draw control types
 */
#define ODT_MENU        1
#define ODT_LISTBOX     2
#define ODT_COMBOBOX    3
#define ODT_BUTTON      4
#if(WINVER >= 0x0400)
#define ODT_STATIC      5
#endif /* WINVER >= 0x0400 */
/*
 * Listbox Styles
 */
#define LBS_NOTIFY            0x0001L
#define LBS_SORT              0x0002L
#define LBS_NOREDRAW          0x0004L
#define LBS_MULTIPLESEL       0x0008L
#define LBS_OWNERDRAWFIXED    0x0010L
#define LBS_OWNERDRAWVARIABLE 0x0020L
#define LBS_HASSTRINGS        0x0040L
#define LBS_USETABSTOPS       0x0080L
#define LBS_NOINTEGRALHEIGHT  0x0100L
#define LBS_MULTICOLUMN       0x0200L
#define LBS_WANTKEYBOARDINPUT 0x0400L
#define LBS_EXTENDEDSEL       0x0800L
#define LBS_DISABLENOSCROLL   0x1000L
#define LBS_NODATA            0x2000L
#if(WINVER >= 0x0400)
#define LBS_NOSEL             0x4000L
#endif /* WINVER >= 0x0400 */
#define LBS_STANDARD          (LBS_NOTIFY | LBS_SORT | WS_VSCROLL | WS_BORDER)
// Measure item implementation relies on unique control/menu IDs
void CWnd::OnMeasureItem(int /*nIDCtl*/, LPMEASUREITEMSTRUCT lpMeasureItemStruct)
{
	if (lpMeasureItemStruct->CtlType == ODT_MENU)
	{
	//	...
	}
	else
	{
		CWnd* pChild = GetDescendantWindow(lpMeasureItemStruct->CtlID, TRUE);
		if (pChild != NULL && pChild->SendChildNotifyLastMsg())
			return;     // eaten by child
	}
	// not handled - do default
	Default();
}

GetDescendantWindow で求めた pChild が NULL のため CListBox::OnChildNotify から MeasureItem が呼ばれない?
呼ばれた時の lpMeasureItemStruct->itemHeight は,ODT_LISTBOX は 18 ,ODT_COMBOBOX は 20 .
デバッガで高さを設定すると,その高さになる.
OWNERDRAWVARIABLE は項目ごとに呼ばれるが,OWNERDRAWFIXED の時はうまくない?


結局,VC 6 などの場合にそうなる(逆にスクロール)様子.
コモンコントロール Ver.6 を使う様にすることで回避できる.
コモンコントロール Ver.6 の指定
VC 6 exe などの場合は (VC6_app).exe.manifest ファイルを用意する.
視覚スタイルを有効にする

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

CComboBox::SetItemHeight (-1,…)

高 DPI 対応で修正していて,コンボボックス(特に,オーナードロー?)の高さが他に比べて不自然.
コンボボックスの高さの変更


ドキュメントを見ると,CB_SETITEMHEIGHT と思うが,指定方法がよくわからない.
コンボボックス 高さ 変更」で 検索する と「できない」と記述されている所もある.


CB_SETITEMHEIGHT で検索していると,-1 を指定しているものがある.
さらに,CB_GETITEMHEIGHT のドキュメントを見ると,次の様にある.

選択フィールドの高さを取得するには、このパラメーターは -1 である必要があります

どうも CB_SETITEMHEIGHT の表現がうまくないものと思う.


次の様なコードで対応.

{
	CRect	rect ;
	m_CtrlStrText.GetClientRect(&rect) ;
	FontFace.SendMessage(CB_SETITEMHEIGHT,-1,rect.Height()) ;
	FontFace.SendMessage(CB_SETITEMHEIGHT, 0,rect.Height()*15/10) ;
	}

CComboBox::SetItemHeight (-1,…)


2023/05/16
ドロップダウンの幅がうまくなかったが,共通コードを見るといろいろ考慮しなければならない部分が多い.
そのため,次の様なコードで対応.

{
	new_w = now_w ;
//	new_w = now_w * 15 / 10 ;
	new_w = int(new_w * ::GetDPI_scale(this->GetSafeHwnd())) ;
	FontFace.SendMessage(CB_SETDROPPEDWIDTH,new_w) ;
	}

SendMessage(CB_SETDROPPEDWIDTH,...)


間違っているかもしれないが,CB_SETITEMHEIGHT を簡単にテストしたことのまとめ.

通常のコンボボックスの場合 -1 で,全ての項目の高さを設定できる
オーナードロー 固定 -1 で,エディットボックス部分の高さを指定
0 で,ドロップ部分の項目の高さを指定
オーナードロー 可変 -1 で,エディットボックス部分の高さを指定
0 以上で,ドロップ部分のそれぞれの高さを指定
Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

CCmdUI::SetText

以前,VC 11 以降で メニューのテキストがうまく更新できない 現象があった.
この時,オーナードローを使っている所は解決した(個人的なコードのバグだった).
が,普通のサブメニューの方はうまくないままとなっていて,それを今回改めて調べてみた.


デバッガで追いかけると,CcmdUI::SetText は呼ばれている.
MFC のコードを見ると,ModifyMenu と SetMenuItemInfo の違いがある.
MFC 10 と 11 の CCmdUI::SetText


サブメニューの場合にうまくないのかと思い,単体テスト用のコードを書いてみたが,再現できない.

void CM_textView::OnUpdateMenuItem(CCmdUI* pCmdUI) 
{
	// TODO: Add your command update UI handler code here
	CString	now = CTime::GetCurrentTime().Format(_T("%H:%M:%S")) ;
	pCmdUI->SetText(now) ;
	}

void CM_textView::OnMenuItem(UINT nID) 
{
	// TODO: Add your command handler code here
	}

何か他の条件があるみたい.


CMenu::TrackPopupMenu で表示するメニューではうまく更新されている.
メニューバーの項目としてコマンドを割り当て,そこから TrackPopupMenu を呼出すことで対応.

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

MFC コントロールのサブクラス化

今まで CWnd::SubclassDlgItem を使ってきたが,DDX_Control も同じ様なことをしているのではと思い調べてみた.


リストボックスをサブクラス化した時の OnInitDialog でのコード.

{
	m_CtrlListFolder.SubclassDlgItem(IDC_LIST_FOLDER,this) ;
	m_CtrlListFolder.Init() ;
	m_CtrlListFolder.ResetContent() ;
	m_CtrlListFolder.SetItemHeight(30) ;
	}

IDC_LIST_FOLDER は,オーナードローリストボックス.
リストボックス オーナードロー
Inside Visual C++ や MFC による Windows 95 プログラミング を参考にしたと思う.
DDX_Control
MFC のバージョンが上がると少しずつ変更が加わっている.
ソースは DlgData.cpp .VC 11 からは WinCore2.cpp .
MFC のソースは難しい.


かなり前の MSDN で次の内容を見つけた.
[MSVC] MFC を使用しての動的サブクラス化
[MSVC] MFC を使用しての動的サブクラス化
DDX_Control でもいけそうな気もするが,…

テクニカル ノート 14:カスタム コントロール

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

AP がうまく動作しない?

作成した AP がうまく動作しなくなってしまった.
AP がうまく動作しない フリーズ?する
起動はするがメニューの「ファイル」の部分を選択したりするとフリーズ?する.
ハッキリわからないが「オーナードローメニュー」か?


PC を再起動することで動作する様にはなったが,原因などが絞れていないのでメモ.


2020/07/07 同じ現象が発生.
サインアウトして入り直しではダメで,PC の再起動の必要がある.

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

ダイアログバーに CCheckListBox

通常のダイアログに CCheckListBox を追加するには,次のような手順.
  CCheckListBox の使い方
ダイアログバーでは,次の様にしてもデータが表示されない.

CCheckListBox*  clb = (CCheckListBox*)m_wndDlgBar.GetDlgItem(IDC_CHECK_LB) ;
clb->AddString("....") ;

以前作成した,オーナー描画のドロップダウンを思い出しコードを見ると,

CMainFrame に変数を追加して,サブクラス化している.
CMainFrame::OnCreate でダイアログバーを Create した後,
 m_ODCB.SubclassDlgItem(IDC_COMBO,&m_wndDlgBar) ;

このコードの最初は,2004/07.
手元にある幾つかの本を見たが見つからなかった.
何を参考にしたかは今となっては不明.


LBN_SELCHANGE で選択された状態がイマイチ.
 内容を更新(PostMessage)するとインデックス 0 の項目に薄い点線が付く.
SendMessage として更新後,選ばれていた項目を SetCurSel することで対応.

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

高 DPI – 3

Win 7 200 % で,コモンダイアログの表示が切れている?
VC 8 の exe では

VC 9 ?以降だと

保存ダイアログでは,

Win 10 では問題ない.


オーナードローリストボックスなどで,高さが足りないものがあった.
  「固定」となっているものがあったので,これは「可変」に.
  初期化動作で,文字により高さを設定する様に変更.
  {
    int itemH = 20 ;
    int textH = int(::GetTextHeight(wnd)*1.5) ;
    this->SetItemHeight(max(itemH,textH)) ;
    }


高 DPI – 1
高 DPI – 2

Is this 投稿 useful? Useful Useless 0 of 0 people say this 投稿 is useful.

CCheckListBox の使い方

1. 通常の手順で,リストボックスをダイアログに貼り付ける.
2. コントロールのプロパティを「オーナー描画」-「固定」,「文字列あり」-「チェック」に変更する.
3. クラスウィザードなどを利用して,コントロールの変数(CListBox)を登録する.
4. ヘッダファイルを開いて,CListBox を CCheckListBox に変更する.
5. 項目の追加は,CListBox などと同様に AddString など.
6. チェックの指定は,SetCheck で.
CheckListBox のプロパティ
CCheckListBox の使い方


「MFC 14 以降で表示がずれる」の対応

Is this 投稿 useful? Useful Useless 1 of 1 people say this 投稿 is useful.