🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

Q&A

解決済

2回答

5981閲覧

リストビューで項目を選択後、フォーカスを失った時に選択行がグレー表示にならないようにするには?

mery

総合スコア27

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Visual C++

Microsoft Visual C++はWindowsのCとC++の統合開発環境(IDE)であり、コンパイラやデバッガを含んでいます。

Win32 API

Win32 APIはMicrosoft Windowsの32bitプロセッサのOSで動作するAPIです。

0グッド

0クリップ

投稿2020/12/28 13:42

編集2020/12/28 21:30

前提・実現したいこと

 下のプログラムでリストビューの項目選択後にボタンを押すと、選択している行の背景色がグレーになってしまいます。
フォーカスを失った時に変更される色を設定する関数があればいいと思い、探してみましたが見つかりませんでした。
また、カスタムドローという方法で出来るかもと思い、いろいろ試してみましたがうまくいきませんでした。

行を選択後にリストビューがフォーカスを失っても選択行の色が変わらないようにするにはどうすればいいですか?

該当のソースコード

c

1 2#include <windows.h> 3#include <CommCtrl.h> 4#pragma comment(lib,"comctl32.lib") 5 6LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM); 7 8TCHAR szClassName[] = TEXT("myprog"); 9HINSTANCE hinst; 10HWND hList=NULL; 11 12 13int WINAPI WinMain(_In_ HINSTANCE hCurInst, _In_opt_ HINSTANCE hPrevInst, 14 _In_ LPSTR lpsCmdLine, _In_ int nCmdShow) 15{ 16 17 hinst = hCurInst; 18 19 MSG msg; 20 BOOL bRet; 21 WNDCLASSEX wc; 22 HWND hWnd; 23 ATOM atom; 24 25 wc.cbSize = sizeof(WNDCLASSEX); 26 wc.style = CS_HREDRAW | CS_VREDRAW; 27 wc.lpfnWndProc = WndProc; 28 wc.cbClsExtra = 0; 29 wc.cbWndExtra = 0; 30 wc.hInstance = hCurInst; 31 wc.hIcon = (HICON)LoadImage(NULL, 32 MAKEINTRESOURCE(IDI_APPLICATION), 33 IMAGE_ICON, 34 0, 35 0, 36 LR_DEFAULTSIZE | LR_SHARED); 37 wc.hCursor = (HCURSOR)LoadImage(NULL, 38 MAKEINTRESOURCE(IDC_ARROW), 39 IMAGE_CURSOR, 40 0, 41 0, 42 LR_DEFAULTSIZE | LR_SHARED); 43 wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); 44 wc.lpszMenuName = NULL; 45 wc.lpszClassName = szClassName; 46 wc.hIconSm = (HICON)LoadImage(NULL, 47 MAKEINTRESOURCE(IDI_APPLICATION), 48 IMAGE_ICON, 49 0, 50 0, 51 LR_DEFAULTSIZE | LR_SHARED); 52 53 if ((atom = RegisterClassEx(&wc)) == 0) 54 return FALSE; 55 56 hWnd = CreateWindow(MAKEINTATOM(atom), 57 TEXT("リストビューのテスト"), 58 WS_OVERLAPPEDWINDOW, 59 0, 60 0, 61 616, 62 400, 63 NULL, 64 NULL, 65 hCurInst, 66 NULL); 67 if (!hWnd) 68 return FALSE; 69 70 ShowWindow(hWnd, nCmdShow); 71 UpdateWindow(hWnd); 72 while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { 73 if (bRet == -1) { 74 break; 75 } else { 76 TranslateMessage(&msg); 77 DispatchMessage(&msg); 78 } 79 } 80 return (int)msg.wParam; 81} 82 83 84LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) 85{ 86 87 LVCOLUMN lvcol; 88 LVITEM item; 89 DWORD dwStyle; 90 static HWND hbutton; 91 LPNMHDR lpnmhdr; 92 LPNMLVCUSTOMDRAW lplvcd; 93 switch (msg) { 94 case WM_CREATE: 95 InitCommonControls(); 96 97 hbutton = CreateWindow(TEXT("BUTTON"), TEXT("ボタン"), WS_CHILD | WS_VISIBLE, 0, 0, 0, 0, hWnd, (HMENU)200, hinst, NULL); 98 99 hList = CreateWindowEx(0,WC_LISTVIEW,0, 100 WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SINGLESEL | LVS_SHOWSELALWAYS, 101 0, 0, 0, 0, 102 hWnd, (HMENU)100, hinst, NULL); 103 104 dwStyle = ListView_GetExtendedListViewStyle(hList); 105 dwStyle |= LVS_EX_FULLROWSELECT | LVS_EX_GRIDLINES; 106 ListView_SetExtendedListViewStyle(hList, dwStyle); 107 108 lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM; 109 lvcol.fmt = LVCFMT_LEFT; 110 lvcol.cx = 300; 111 lvcol.pszText = TEXT("タイトル1"); 112 lvcol.iSubItem = 0; 113 ListView_InsertColumn(hList,0,&lvcol); 114 115 lvcol.pszText = TEXT("タイトル2"); 116 lvcol.iSubItem = 1; 117 ListView_InsertColumn(hList, 1, &lvcol); 118 119 item.mask = LVIF_TEXT; 120 item.pszText = TEXT("文字列"); 121 item.iItem = 0; 122 item.iSubItem = 0; 123 ListView_InsertItem(hList,&item); 124 125 item.pszText = TEXT("文字列"); 126 item.iItem = 1; 127 item.iSubItem = 0; 128 ListView_InsertItem(hList, &item); 129 130 item.pszText = TEXT("文字列"); 131 item.iItem = 0; 132 item.iSubItem = 1; 133 ListView_SetItem(hList, &item); 134 135 item.pszText = TEXT("文字列"); 136 item.iItem = 1; 137 item.iSubItem = 1; 138 ListView_SetItem(hList, &item); 139 140 break; 141 case WM_NOTIFY: 142 143 lpnmhdr = (LPNMHDR)lp; 144 if (lpnmhdr->code == NM_CUSTOMDRAW) { 145 lplvcd = (LPNMLVCUSTOMDRAW)lp; 146 switch (lplvcd->nmcd.dwDrawStage) { 147 case CDDS_PREPAINT: 148 return CDRF_NOTIFYITEMDRAW; 149 case CDDS_ITEMPREPAINT: 150 151 //CDIS_GRAYED以外のCDIS_SELECTEDやCDIS_DISABLEDと比較してもうまくいかなかった 152 if (lplvcd->nmcd.uItemState == CDIS_GRAYED) { 153 lplvcd->clrText = RGB(255, 255, 255); 154 lplvcd->clrTextBk = RGB(0, 0, 255);//行選択時の背景色が分からないので適当 155 } 156 break; 157 } 158 159 } 160 break; 161 case WM_SIZE: 162 MoveWindow(hList, 0, 0, LOWORD(lp), HIWORD(lp)/2, TRUE); 163 MoveWindow(hbutton, 0, HIWORD(lp) / 2, LOWORD(lp), HIWORD(lp) / 2+1, TRUE); 164 break; 165 166 case WM_DESTROY: 167 PostQuitMessage(0); 168 break; 169 default: 170 return (DefWindowProc(hWnd, msg, wp, lp)); 171 } 172 return 0; 173} 174 175

補足情報(FW/ツールのバージョンなど)

Microsoft Visual Studio Community 2019
Microsoft Visual C++ 2019 C言語
WIN32 ユニコードビルド Windows10

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KoichiSugiyama

2020/12/28 16:58

「カスタムドローという方法で出来るかもと思い、いろいろ試してみましたがうまくいきませんでした。」とありますが、そこまでたどり着いたのであれば、ちょっとした勘違いで動かなかっただけかもしれません。せっかく書いたのですから動いていなくてもその部分のソースを記載していただいた方がアドバイスが集まりやすいと思います。
mery

2020/12/28 21:26

回答ありがとうございました。 ソースコードを試した例の1つに変更しました。
guest

回答2

0

自己解決

何度も回答していただいたKoichiSugiyamaさんには申し訳ないですが、カスタムドローでやる方法はうまくいかなかったので別の方法を考えてやってみたらうまくいきました。
解決した方法は、リストビューをサブクラス化して、その中に
case WM_KILLFOCUS:
return 0;
を追加で出来ました。
デフォルトのWM_KILLFOCUSの中で実行されているのが選択行の色をグレーにする以外にも何かやっているとしたら問題が起こるかもしれませんが・・・。

投稿2020/12/29 21:30

mery

総合スコア27

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

実際に動かしていませんので、外していたらすみませんが

c++

1if (lplvcd->nmcd.uItemState == CDIS_GRAYED) { 2 lplvcd->clrText = RGB(255, 255, 255); 3 lplvcd->clrTextBk = RGB(0, 0, 255);//行選択時の背景色が分からないので適当 4} 5

この部分、lplvcd->nmcd.uItemStateにCDIS_GRAYEDのみ設定されている状態ってあまりないんじゃないでしょうか。こういったステータスを表す変数は、複数の状態を表現できるように、変数の各ビットが意味を持つような設計がされていることが多いです。
ですので、CDIS_GRAYEDのビットが立っているかのチェックに切り替えてみてはどうでしょうか。

C++

1if (lplvcd->nmcd.uItemState & CDIS_GRAYED) { 2 : 3 :

デバッガで止めてみて、どのような値が入っているか確認してみてください。

追記
コメントから513という値が返ってきていた、とのことで、この見方を書いておきます。
まず513という値を16進数で表示します(Windows付属の電卓でやるなり、VisualStudioの機能で16進表示するなりしてみてください)。
そうすると、

513 = 0x201

であることがわかると思います。次に、commctrl.hのCDIS_GRAYED辺りを調べると、

c

1// itemState flags 2#define CDIS_SELECTED 0x0001 3#define CDIS_GRAYED 0x0002 4#define CDIS_DISABLED 0x0004 5#define CDIS_CHECKED 0x0008 6#define CDIS_FOCUS 0x0010 7#define CDIS_DEFAULT 0x0020 8#define CDIS_HOT 0x0040 9#define CDIS_MARKED 0x0080 10#define CDIS_INDETERMINATE 0x0100 11#if (NTDDI_VERSION >= NTDDI_WINXP) 12#define CDIS_SHOWKEYBOARDCUES 0x0200 13#endif 14#if (NTDDI_VERSION >= NTDDI_VISTA) 15#define CDIS_NEARHOT 0x0400 16#define CDIS_OTHERSIDEHOT 0x0800 17#define CDIS_DROPHILITED 0x1000 18#endif

という記述が見つかると思います。つまり0x201は上記状態フラグで言うと

0x201 = CDIS_SELECTED + CDIS_SHOWKEYBOARDCUES

であることがわかります。つまり選択されているということと、キーボードキューであるという複数の状態が含まれています。
選択状態の時に、フォーカスが無くても色をグレーに変えたくなければ、

C++

1if (lplvcd->nmcd.uItemState & CDIS_SELECTED) { 2 : 3 :

のように条件を変えて、背景青の文字色白で描き直してやれば良い、ということになります。特に色を変える必要がない場合、標準の処理を通るように記述するか、ご自身でデフォルトの色で描いてやらないと色が戻らないかもしれません。この辺りは実際に動かしてみて調整してください。

投稿2020/12/29 00:18

編集2020/12/29 07:06
KoichiSugiyama

総合スコア3041

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mery

2020/12/29 00:53

回答ありがとうございます。CDIS_GRAYEDのビットが立っているかのチェックの下の行にブレークポイントを設定し試してみましたが、そこで止まりませんでした。 CDIS_GRAYEDの状態の「アイテムは灰色表示になっている」という意味は背景色がグレイになった状態ではないのですか?
KoichiSugiyama

2020/12/29 01:06

今ちょっとすぐには調べられないので、推測で申し訳ないですが、灰色表示は無効時(DISABLE)の時に設定されるのではないかと思います。今回のパターンだと、選択中・フォーカス無のような状態の時の色が灰色なだけで、状態としての灰色とは違うのではないかと思います。
mery

2020/12/29 01:35

uItemStateの値には他にCDIS_DISABLED(アイテムは使用不可になっている)というのがあるので何か別な意味があるような気がします。他の理由が思いつきませんが・・・。
KoichiSugiyama

2020/12/29 02:44

uItemStateに実際にどういう値が入っているのかは確認されましたか?入ってきた値から、現在どういう状態なのか確認できると思います。
mery

2020/12/29 06:43

判定文を抜けたところで調べるとuItemStateには513という値が入っていました。この値からどういう状態なのか確認する方法は私には分かりません。どうやって確認すればいいのですか?
KoichiSugiyama

2020/12/29 06:49

コメントに角のは長くなるので、回答の方に追記します。
mery

2020/12/29 08:40

詳しく教えていただきありがとうございます。 値から状態を確認する方法はわかりましたが、「選択されているということと、キーボードキューであるという複数の状態が含まれています。」というところの「選択されている」の部分が納得いかないです。 私のプログラムを実行すると最初はどこも選択していないので、マウスで行をクリックするまでは選択されている状態にはならないと思うのですが・・・。 起動時にListView_GetNextItemで選択行を調べると-1が返されるので最初は選択されていない状態だと思います。uItemStateの値は行クリック前とクリック後のどちらでも513でした。
KoichiSugiyama

2020/12/29 11:48

すみません、推測ですが、リストに値をセットするときは選択状態になるのではないでしょうか。このタイミングでイベントが発生して該当処理を通るのではないかと思います。なので、初期化が終了するまで(値のセットが終わるまで)フラグなどを使って、イベントが来ても処理しない等の調整が必要なのではないかと思います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.36%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問