
VC++2005のMFC環境でプログラムを作成しています。
リストコントロールのイベント(LVN_KEYDOWN)よりハンドラを作成し、
下記のような実装を行い、最下行からさらに下キーを押下した際に、
最上行に選択フォーカスを移動させたいのですが、
青いフォーカスは上に移動しますが、点線のボックスが最下行に
そのまま残ってしまい、その後もおかしな動きをしてしまいます。
何か実装で間違っている点があるのでしょうか?
解決策をご存知の方おられましたら、ご教示お願いいたします。
下記が問題のソースコードです。
void CtestListDlg::OnLvnKeydownList1(NMHDR *pNMHDR, LRESULT *pResult)
{
LV_KEYDOWN *pNMLV = reinterpret_cast<LV_KEYDOWN*>(pNMHDR);
int ret = m_listTest.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);
if(ret==-1) return;
if(pNMLV->wVKey==VK_UP){
if(ret==0){
int count = m_listTest.GetItemCount();
m_listTest.SetItemState(count-1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED);
}
else{
m_listTest.SetItemState(ret-1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED);
}
}
if(pNMLV->wVKey==VK_DOWN){
int count = m_listTest.GetItemCount();
if(ret==count-1){
m_listTest.SetItemState(0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED);
}
else{
m_listTest.SetItemState(ret+1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED);
}
}
*pResult = 0;
}

No.2ベストアンサー
- 回答日時:
こんにちは。
SetItemStateの最後のフラグが不完全なのでは。
以下ですと、選択状態に成るだけで、フォーカスまでは入らないです。
m_listTest.SetItemState(count-1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED);
m_listTest.SetItemState(count-1, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
とすればフォーカスも移動出来ます。
後は「↓または↑」を押して、「最下行⇔最上行へスクロール」する処理を行った場合は、pResultに1を入れて直ちに制御を戻します。
其れ以外の場合は、pResultは0です。
void CTestDlg::OnLvnKeyDown(NMHDR *pNMHDR, LRESULT *pResult)
{
LPNMLVKEYDOWN pNMLV = reinterpret_cast<LPNMLVKEYDOWN>(pNMHDR);
// TODO: ここにコントロール通知ハンドラ コードを追加します。
int ret = m_listTest.GetNextItem(-1, LVNI_ALL | LVNI_SELECTED);
if(ret==-1)
return;
int count = m_listTest.GetItemCount();
int LVIS = LVIS_SELECTED | LVIS_FOCUSED;
if(pNMLV->wVKey == VK_UP)
{
//最上行にぶつかったら
if(ret == 0)
{
m_listTest.SetItemState(count-1, LVIS, LVIS);
*pResult = 1;
return;
}
}
if(pNMLV->wVKey == VK_DOWN)
{
//最下行にぶつかったら
if(ret == count-1)
{
m_listTest.SetItemState(0, LVIS, LVIS);
*pResult = 1;
return;
}
}
//其れ以外の位置なら
m_listTest.SetItemState(ret, LVIS, LVIS);
*pResult = 0;
}
この回答への補足
ご回答ありがとうございます。
確かにご提示頂いた方法で、期待動作をさせることが出来ました。
ありがとうございました。
ここからは、方法についての疑問点なのですが、
>pResultに1を入れて直ちに制御を戻します。其れ以外の場合は、pResultは0です。
とありますが、pResultの値が0と1とでは、
どのような意味の違いがあるのかが分かりません。
もし宜しければ、お手数おかけしますが、
こちらの疑問点につきましても、お答え願えませんでしょうか?
No.3
- 回答日時:
こんにちは。
補足頂きました。此れを説明するのは困難です。http://msdn.microsoft.com/ja-jp/library/1ssc6038 …
イベントハンドラの種類やコントロールの種類によってまちまちですので、一概には言えないのですが、少なくともLVN_KEYDOWNイベントハンドラにおいて、簡単に言えば、pResult = 0でデフォルト処理へ渡され、pResult = 1で、自分自身の行った処理が全てになる、と言う事でしょうか。
其の侭デフォルト処理が行われると、折角自前で行った処理が上重ねされてしまい、台無しになる事があります。
例えば提示したサンプル中のpResult = 1の部分をpResult = 0にした場合、移動すると、もう一つ分余計に移動してしまいます(2個分移動してしまう)。
要は、自前で「最上行⇔最下行」へ移動する処理を自前で行っておきながら、デフォルト処理へ渡してしまうと、其の中でも移動処理が成される為、一つ分余計に移動する現象が起きる、と言った具合です。
MFCに関わらず、WindowsAPI関連の実装は、常にこの様な病的な現象が呪いの如くについて回ります。
此れに太刀打ちするは、経験や体験、実験を重ねる事でしかないと思っています。
ご回答ありがとうございます。
確かにpResult = 1の部分をpResult = 0にした場合、
期待動作をさせることは出来ませんでした。
勉強になりました。ありがとうございました。
No.1
- 回答日時:
SetItemState()は「見た目」しか変わりません。
見た目だけ変えても「今、本当に選ばれているもの」は変化しません。「今、本当に選ばれているもの」はSetHotItem()じゃないと変わりません。
つまり、現状のままでは「見た目だけ最上行⇔最下行に行き来してるように見えるけど、本当に選ばれているものは何も変わってないから、その後もおかしな動きをしているように見える」のです。
試してないですが、SetHotItem()を行うと、自動的に見た目も変わるかも知れません(SetItemState()を呼ばなくても良いかも知れない?)
なお、SetHotItem()を行う時に「選ぼうとしたアイテムがリストの外にスクロールアウトして見えてない状態」の時は、自動でスクロールしてくれないかも知れないので、その場合、EnsureVisible()を使って、選ぼうとしたアイテムがリスト内に表示されるようにすれば、スクロールインしてくると思います。
まとめると、選択アイテムを変更する場合は
SetItemState()で見た目を変える。
SetHotItem()で選択アイテムを変える。
EnsureVisible()で必ず見える状態にする。
と言う3つの処理をセットで行わないと駄目だと思います。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミング c言語 4 2023/03/07 01:05
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- C言語・C++・C# c言語の問題です 3 2023/01/10 16:15
- C言語・C++・C# C言語 3 2022/11/09 13:27
- Ruby 【JAVA】数字をひし形に出力するプログラムについて 2 2022/07/11 23:32
- C言語・C++・C# c言語の問題の説明、各所ごとに 5 2023/07/26 11:03
- Visual Basic(VBA) Dateserialで データ抽出 2 2022/06/26 21:07
- C言語・C++・C# Cのオブジェクトファイルの逆アセンブル 5 2023/05/13 01:51
- PHP PHPでCookieを使った訪問回数について 1 2023/05/28 14:10
- 英語 The P2s and P4s of bilateral mandible were extract 1 2022/12/11 18:09
このQ&Aを見た人はこんなQ&Aも見ています
関連するカテゴリからQ&Aを探す
おすすめ情報
このQ&Aを見た人がよく見るQ&A
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
英語の知識があって、数学の知...
-
エクセルで、日付を入力すると...
-
「ご処理進めて頂きますようお...
-
男性に対して、『女性への気遣...
-
内部処理形式ってなんですか
-
ハードウェア処理とソフトウェ...
-
カスタムドロー
-
VBA Progress barが動作しない
-
生ゴミ処理機の処理中のにおい...
-
VBAでCOPYを繰り返すと、処理が...
-
リョウ・・・量?料?
-
皆さんが1番信じているものはな...
-
VBAでループ内で使う変数名を可...
-
プロファイラ VC++6
-
Escキーを押しても中断されなか...
-
ifの条件式
-
Excelプロセスの起動
-
[Excel VBA]Doloop途中のifで処...
-
メルカリのメルカードで買い物...
-
インテル(R) Pentium(R) プロセ...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
「ご処理進めて頂きますようお...
-
エクセルで、日付を入力すると...
-
VBAでループ内で使う変数名を可...
-
【Excel】特定の文字を含むセル...
-
switch の範囲指定
-
EXCEL VBA マクロ 実行する度に...
-
UMLでの例外処理
-
DoEventsがやはり分からない
-
月度は何て読みますか?
-
お家デートをしててハグを長い...
-
VB.NET Excelを読み込んでDataT...
-
VBの質問#if 0 then ってどう...
-
Do~Loopした回数をカウントしたい
-
VBAでCOPYを繰り返すと、処理が...
-
メルカリのメルカードで買い物...
-
インタラクティブの反対語は?
-
Loadイベント中にほかのイベン...
-
リョウ・・・量?料?
-
vba 空のデータをSplitする時の...
-
findは動くがfindnextがマクロ...
おすすめ情報