スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

--.--.-- | スポンサー広告

リストビューのサブアイテムの直接編集2

前回からの続き

リストビューの初期化が終わったところで
いよいよサブアイテムの編集を行えるようにコードを実装します。

※リストビューのスタイルに LVS_EDITLABELS を指定するのを忘れずに


LRESULT APITestMain::EditLabel(LV_DISPINFO* Info)
{
switch (Info->hdr.code)
{
case LVN_BEGINLABELEDIT:
{
// ターゲット場所を調査
POINT cursor;
::GetCursorPos(&cursor);
::ScreenToClient(m_ListWnd, &cursor);

LV_COLUMN lvc;
lvc.mask = LVCF_WIDTH;

RECT rect;
ListView_GetItemRect(m_ListWnd, Info->item.iItem, &rect, LVIR_LABEL);

if(::PtInRect(&rect, cursor))
m_EditColumn = 0;

int col = 1;
while(m_EditColumn == -1 && ListView_GetColumn(m_ListWnd, col, &lvc))
{
rect.left = rect.right;
rect.right += lvc.cx;

if(::PtInRect(&rect, cursor))
m_EditColumn = col;

col++;
}

// マウスをクリックした位置がアイテム外だったら編集キャンセル
if(m_EditColumn == -1)
{
// ※1
::SetWindowLongPtr(m_hWnd, DWLP_MSGRESULT, TRUE);
return TRUE;
}

m_EditRow = Info->item.iItem;

// エディットボックスをサブクラス化
HWND edit_wnd = ListView_GetEditControl(m_ListWnd);
m_EditItem.Attach(edit_wnd);
m_EditItem.SetPos(rect.left, rect.top);

// エディットボックスのテキストの内容をターゲットのアイテムの内容に書き換え
TCHAR buffer[256] = _T("");
ListView_GetItemText(m_ListWnd, Info->item.iItem, m_EditColumn,
buffer, 255);
::SetWindowText(edit_wnd, buffer);
break;
}

case LVN_ENDLABELEDIT:
if(Info->item.pszText != NULL)
ListView_SetItemText(m_ListWnd, Info->item.iItem, m_EditColumn,
Info->item.pszText);

m_EditColumn = -1;
m_EditItem.Detach();
ListView_SetItemState(m_ListWnd, Info->item.iItem, 0,
LVNI_FOCUSED | LVNI_SELECTED);

break;
}

return FALSE;
}


# m_EditRow は編集ターゲットの行番号を
# m_EditColumn は列番号を保持しています
# m_EditItem はエディットボックスをサブクラス化するためのクラス変数、詳細は後述

やっていることは至極単純で早い話が
LVN_BEGINLABELEDIT メッセージが発行された際に
通常であれば先頭のカラムに表示されるはずのエディットボックスを
強制的に編集のターゲットとなったアイテムの場所へ移動
させています。

ちなみに呼び出し元はこうなっています。

//--------------------------------------------------------------
// ウインドウプロシージャ
//--------------------------------------------------------------
LRESULT APITestMain::WndProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{

case WM_NOTIFY:
// IDC_LISTVIEW はリストビューのリソースID
if((int)wParam == IDC_LISTVIEW)
{
LV_DISPINFO* info = reinterpret_cast<LV_DISPINFO *>(lParam);
return EditLabel(info);
}

break;

}

return FALSE;
}


さて強制的に移動させる……と言っている割には
MoveWindow API 等が出てきていません。
というのも実はアイテム編集時に出てくるエディットボックスは
内部で強制的に座標を移動させるようになっているらしく
MoveWindow API 等移動させようとしても元の位置に戻ってしまうのです。
そのためエディットボックスをサブクラス化して座標の位置を固定化させます。

# なおサブクラス化にあたって belution というサイトにある
# CWndBase クラスを使用しています
# http://techtips.belution.com/ja/vc/0009/


#include "EditSubItem.h"

// コンストラクタ
EditSubItem::EditSubItem()
{
m_Position.x = 0;
m_Position.y = 0;
}

// デストラクタ
EditSubItem::~EditSubItem()
{

}

// 固定する座標を保存
void EditSubItem::SetPos(int Left, int Top)
{
m_Position.x = Left;
m_Position.y = Top;
}

LRESULT EditSubItem::WndProc(HWND hWnd, UINT uMsg,
WPARAM wParam, LPARAM lParam)
{
switch(uMsg)
{
case WM_WINDOWPOSCHANGING:
{
LPWINDOWPOS pos = (LPWINDOWPOS)lParam;
pos->x = m_Position.x;
pos->y = m_Position.y;
break;
}
}

return CallWindowProc(m_lpfnOldWndProc, hWnd, uMsg, wParam, lParam);
}


以上で完成!
・・・・・・
実際動かしてみればわかると思いますが表示周りがおかしいことに気づくはずです。
それもそのはず、強制的にエディットボックスを動かしたのだから
当然元のアイテムの文字列が消えたままです。
しかもエディットボックスを移動した先のアイテムの文字列も
(エディットボックスの)下に表示されたままです。
これを解消するにはオーナードローを行います。

次回に続く

※1
今回ダイアログベースで作成したため
編集をキャンセルするためには直接ウインドウに返値を渡してあげる必要がある
理由は
http://blogs.msdn.com/oldnewthing/archive/2003/11/07/55619.aspx
ん~個人的にあまり納得できない( ´・ω・)

スポンサーサイト

テーマ:プログラミング - ジャンル:コンピュータ

2007.06.23 | Comments(0) | Trackback(0) | プログラム

リストビューのサブアイテムの直接編集

現在マップエディタを作成しているのですが
(といっても身辺整理中に付き進行が遅い・・・・・・)
データ用のレイヤーの編集を行う際、
リストビューのアイテムを直接編集できると便利だよなあ~と
考えたのですが・・・・・・
そういや先頭のカラム以外の編集ってデフォルトではできないことに気づき
('A`)←しばらくこんな顔になっていました。

というわけで今回は SDK でリストビューのサブアイテムを編集する方法について。

# 方法については某所を参考にしています

まずはコード(一部のみ抜粋)


/* ダイアログベースアプリで作成してます */

// 初期化部分
BOOL APITestMain::InitDialog(LPARAM lParam)
{
// コモンコントロールの初期化
INITCOMMONCONTROLSEX ic;
ic.dwSize = sizeof(INITCOMMONCONTROLSEX);
ic.dwICC = ICC_LISTVIEW_CLASSES;
::InitCommonControlsEx(&ic);

// リストビューのハンドルを取得
m_ListWnd = ::GetDlgItem(hWnd, IDC_LISTVIEW);

// リストビューのヘッダの作成
CreateHeader();

// リストビューのアイテムの作成
AddItems(_T("item1"), _T("value1"));
AddItems(_T("item2"), _T("value2"));
AddItems(_T("item3"), _T("value3"));

return TRUE;
}

// リストビューのヘッダの作成
void APITestMain::CreateHeader()
{
LV_COLUMN lvcol;
lvcol.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
lvcol.fmt = LVCFMT_LEFT;
lvcol.cx = 150;
lvcol.pszText = _T("Name");
lvcol.iSubItem = 0;
ListView_InsertColumn(m_ListWnd, 0, lvcol);

lvcol.cx = 150;
lvcol.pszText = _T("Value");
lvcol.iSubItem = 1;
ListView_InsertColumn(m_ListWnd, 1, lvcol);
}

// リストビューのアイテムの追加作成
void APITestMain::AddItems(TCHAR* Name, TCHAR* Value)
{
int count = ListView_GetItemCount(m_ListWnd);

SetItems(count, Name, Value);
}

// リストビューのアイテムの作成
void APITestMain::SetItems(int Item, TCHAR* Name, TCHAR* Value)
{
LV_ITEM item;

memset(&item, 0, sizeof(LV_ITEM));

item.mask = LVIF_TEXT;
item.pszText = Name;
item.iItem = Item;
item.iSubItem = 0;
ListView_InsertItem(m_ListWnd, &item);

item.pszText = Value;
item.iSubItem = 1;
ListView_SetItem(m_ListWnd, &item);
}


リストビューを使うにあたっての初期化周りです。
まあいつものやつですね。

次回に続く
# 2007/6/23 ちょこっとコードを編集

テーマ:プログラミング - ジャンル:コンピュータ

2007.06.23 | Comments(0) | Trackback(0) | プログラム

復活~

どうもプログラマーのケルプです(´・ω・`)

ようやく復活できました。
ゲームの製作も随時行っていこうと思うので楽しみに・・・・・・
待っている人はいないか

ゲーム画面


久しぶりなので簡易なゲームになる予定です。

これが完成したらストローク2でも作ろうかと。
今度はアイテムが登場する予定です(`・ω・´)

テーマ:プログラミング - ジャンル:コンピュータ

2007.06.02 | Comments(0) | Trackback(0) | プログラム

«  | HOME |  »

ブロとも申請フォーム

この人とブロともになる

カウンター


上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。