-
Здравствуйте. Не могу разобраться в перемещение элементов. В LVN_BEGINDRAG номер ITEMa, а как быть дальше не знаю. В справке MSDN не примера на эту тему. Помогите пожалуйста. Создание окна и ListView.
unit Unit1;
interface
uses
Windows, Messages, CommCtrl, SysUtils;
Function WinProc(Wnd: hwnd; Msg : UINT; WParam : WPARAM; LParam: LPARAM): lresult; Stdcall;
Procedure WinMain;
var
WndClassEx : TWndClassEx;
FormMy, LV : HWND;
MMsg: Msg;
XScreen, YScreen : Integer;
implementation
var
FormRect : TRect;
Const
LVID = 13;
Function WinProc(Wnd: HWND; Msg : UINT; WParam : WPARAM; LParam: LPARAM): lresult; Stdcall;
Var
lvc : TLVColumn;
I, B : Integer;
Item : TLVItem;
Begin
Result := 0;
Case Msg Of
WM_CREATE:
begin
LV := CreateWindowEx(WS_EX_CLIENTEDGE,'SysListView32', '1', WS_CHILD or WS_VISIBLE or LVS_REPORT or LVS_SHOWSELALWAYS
or LVS_SINGLESEL, 0, 0, FormRect.Right, FormRect.Bottom,Wnd, LVID, HInstance, nil);
SendMessage(lv, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_DOUBLEBUFFER or LVS_EX_HEADERDRAGDROP or LVS_EX_BORDERSELECT or LVS_EX_FULLROWSELECT or LVS_EX_GRIDLINES or LVS_EX_INFOTIP);
SendMessage(LV, LVM_SETTEXTBKCOLOR, 0, 12632256);
SendMessage(LV, LVM_SETBKCOLOR, 0, 12632256);
lvc.fmt := LVCFMT_CENTER;
lvc.mask := LVCF_TEXT or LVCF_WIDTH;
lvc.pszText := '0';
lvc.cx := 70;
lvc.iSubItem := 0;
ListView_InsertColumn(lv, 0, lvc);
lvc.mask := lvc.mask or LVCF_FMT or LVCF_SUBITEM or LVCF_ORDER;
for I := 1 to 7 do
begin
lvc.pszText := PChar(IntToStr(I));
lvc.iSubItem := I;
lvc.iOrder := I;
ListView_InsertColumn(LV, I, lvc);
end;
for I := 0 to 6 do
begin
FillChar(Item, sizeof(Item), 0 );
Item.mask := LVIF_TEXT;
Item.iItem := ListView_GetItemCount(LV);
Item.pszText := PChar(IntToStr(I));
ListView_InsertItem(LV, Item);
for b := 0 to 6 do
begin
Item.iSubItem := B + 1;
Item.pszText := PChar(IntToStr(Random(100)));
ListView_SetItem(LV, Item);
end;
end;
end;
WM_NOTIFY:
begin
if PNMHDR(lParam).hwndFrom = LV then
case PNMHDR(lParam).code of
LVN_BEGINDRAG:
begin
SetWindowText(Wnd, IntToStr(PNMListView(LParam).iItem)); end;
end;
end;
WM_SIZE:
Begin
if WParam <> SIZE_MINIMIZED then
begin
GetClientRect(Wnd, FormRect);
SetWindowPos(LV, 0, 0, 0, FormRect.Right, FormRect.Bottom - 50, SWP_NOZORDER);
end;
End;
WM_CLOSE:
begin
DestroyWindow(LV);
DestroyWindow(Wnd);
end;
WM_DESTROY: PostQuitMessage(0);
Else
Result := DefWindowProc(Wnd, Msg, WParam, LParam);
End;
End;
Procedure WinMain;
Begin
XScreen := (GetSystemMetrics(SM_CXSCREEN)); YScreen := (GetSystemMetrics(SM_CYSCREEN));
FillChar(WndClassEx, SizeOf(TWndClassEx), 0);
WndClassEx.cbSize := SizeOf(TWndClassEx);
WndClassEx.lpszClassName := 'APIWindow';
WndClassEx.style := CS_HREDRAW Or CS_VREDRAW;
WndClassEx.hInstance := HInstance;
WndClassEx.lpfnWndProc := @WinProc;
WndClassEx.cbClsExtra := 0;
WndClassEx.cbWndExtra := 0;
WndClassEx.hIcon := LoadIcon(HInstance, MakeIntResource('MAINICON'));
WndClassEx.hIconSm := LoadIcon(HInstance, MakeIntResource('MAINICON'));
WndClassEx.hCursor := LoadCursor(0, IDC_ARROW);
WndClassEx.hbrBackground := GetStockObject(LTGRAY_BRUSH);
WndClassEx.lpszMenuName := NIL;
If RegisterClassEx(WndClassEx) = 0 Then
MessageBox(0, 'Невозможно зарегистрировать класс окна', 'Ошибка', MB_OK Or MB_ICONHAND)
Else
Begin
FormMy := CreateWindowEx(0 , WndClassEx.lpszClassName, 'ListView', WS_CLIPCHILDREN or WS_OVERLAPPEDWINDOW,
(XScreen - 500) div 2, (YScreen - 300) div 2, 500, 300, 0, 0, HInstance, NIL);
If FormMy = 0 Then
MessageBox (0, 'Окно не создано!', 'Ошибка', MB_OK Or MB_ICONHAND)
Else
Begin
ShowWindow(FormMy, SW_SHOWNORMAL);
UpdateWindow(FormMy);
While GetMessage(MMsg, 0, 0, 0) Do
Begin
TranslateMessage(MMsg);
DispatchMessage(MMsg);
End;
Halt(MMsg.WParam);
UnregisterClass(WndClassEx.lpszClassName, HInstance);
End;
End;
End;
end.
-
нашел На C++. Переделал. Но не работает , т.е. зажимаю лкм, начинаю ташить, появл. картинка с элементом и сдвигается немного и все. Мышью можно двигать бесконечно, картинка застывает. Сабклассировал WM_MOUSEMOVE для ListView для получения координат мыши относительно ListView, но при зажатой мыши координаты не меняются:
var FormRect : TRect;
iHeight, iPos, iRet : Integer; hDragImageList : HIMAGELIST; hOneImageList, hTempImageList : HIMAGELIST; bDragging, bFirst : BOOL; lvhti : tLVHITTESTINFO; imf : IMAGEINFO; Item : TLVItem; P, pt : TPoint; buf : PChar;
Function LVWinProc(Wnd: THandle; Msg: Cardinal; WParam, LParam: Integer): Cardinal; Stdcall; Begin Case Msg Of WM_MOUSEMOVE: begin if bDragging then Exit;
p.x := LOWORD(lParam); p.y := HIWORD(lParam); ImageList_DragMove(p.x, p.y); SetWindowText(FormMy, PChar(IntToStr(p.y))); Exit; end; End; Result := CallWindowProc(Pointer(GetWindowLong(Wnd, GWL_USERDATA)), wnd, Msg, WParam, LParam); End;
После создания ListView:
SetWindowLong(LV, GWL_USERDATA, SetWindowLong(LV, GWL_WNDPROC, LongInt(@LVWinProc)));
И WM_NOTIFY
WM_NOTIFY: begin if PNMHDR(lParam).hwndFrom = LV then case PNMHDR(lParam).code of LVN_BEGINDRAG: begin // { ListView_CreateDragImage(LV, 1, fff); // SetWindowText(Wnd, IntToStr({PNMListView(LParam).iItem)); //}PNMListView(LParam).ptAction.X) + ' ' + IntToStr(PNMListView(LParam).ptAction.Y)) ;
p.x := 8; p.y := 8;
// Ok, now we create a drag-image for all selected items bFirst := TRUE; iPos := ListView_GetNextItem(LV, -1, LVNI_SELECTED); while (iPos <> -1) do begin if bFirst then begin // For the first selected item, // we simply create a single-line drag image hDragImageList := ListView_CreateDragImage(LV, iPos, p); ImageList_GetImageInfo(hDragImageList, 0, imf); iHeight := imf.rcImage.Bottom; bFirst := FALSE; // Break; end else begin // For the rest selected items, // we create a single-line drag image, then // append it to the bottom of the complete drag image hOneImageList := ListView_CreateDragImage(LV, iPos, p); hTempImageList := ImageList_Merge(hDragImageList, 0, hOneImageList, 0, 0, iHeight); ImageList_Destroy(hDragImageList); ImageList_Destroy(hOneImageList); hDragImageList := hTempImageList; ImageList_GetImageInfo(hDragImageList, 0, imf); iHeight := imf.rcImage.bottom; // Break; end;
iPos := ListView_GetNextItem(LV, iPos, LVNI_SELECTED);
end;
// Now we can initialize then start the drag action ImageList_BeginDrag(hDragImageList, 0, 0, 0);
pt := PNMListView(LParam).ptAction; // ClientToScreen(LV, pt);
ImageList_DragEnter({GetDesktopWindow()} LV, p.x, pt.y);
bDragging := TRUE; // ImageList_EndDrag(); // Don't forget to capture the mouse SetCapture(Wnd);
Exit; end;
end; end;
WM_LBUTTONUP: begin // MessageBox(Wnd,'','',0); // End the drag-and-drop process bDragging := FALSE; ImageList_DragLeave(LV); ImageList_EndDrag(); ImageList_Destroy(hDragImageList);
ReleaseCapture();
// Determine the dropped item
{ lvhti.pt.x := LOWORD(lParam); lvhti.pt.y := HIWORD(lParam); ClientToScreen(Wnd, &lvhti.pt); ScreenToClient(LV, &lvhti.pt); ListView_HitTest(LV, &lvhti);
// Out of the ListView? if lvhti.iItem = -1 then Exit; // Not in an item? if ((lvhti.flags and LVHT_ONITEMLABEL = 0) and (lvhti.flags and LVHT_ONITEMSTATEICON = 0)) then Exit;
// Dropped item is selected? Item.iItem := lvhti.iItem; Item.iSubItem := 0; Item.mask := LVIF_STATE; Item.stateMask := LVIS_SELECTED; ListView_GetItem(LV, Item);
if (Item.state = LVIS_SELECTED) then Exit;
// Rearrange the items iPos := ListView_GetNextItem(LV, -1, LVNI_SELECTED); while iPos <> -1 do begin // First, copy one item Item.iItem := iPos; Item.iSubItem := 0; //Item.cchTextMax := MAX_TARGET_LEN; Item.pszText := buf; Item.stateMask := LVIS_SELECTED; Item.mask := LVIF_STATE or LVIF_IMAGE or LVIF_INDENT or LVIF_PARAM or LVIF_TEXT; ListView_GetItem(lv, Item); Item.iItem := lvhti.iItem; // Insert the main item iRet := ListView_InsertItem(LV, Item); if Item.iItem < iPos then inc(lvhti.iItem); if (iRet <= iPos) then inc(iPos); // Set the subitem text for i := 1 to 6 do begin ListView_GetItemText(lv, iPos, i, buf, SizeOf(Buf)); ListView_SetItemText(LV, iRet, i, buf); end;
// Delete from original position ListView_DeleteItem(LV, iPos); iPos := ListView_GetNextItem(LV, -1, LVNI_SELECTED); end; }
// Exit; end;
-
-
Вроде Получилось.
Перемещение элемента вверх работает. А вот вниз нет, голова уже не соображает. Может кто увидит проблему и подскажет ее решение.
unit Unit1;
interface
uses Windows, Messages, CommCtrl, SysUtils;
Procedure WinMain;
var WndClassEx : TWndClassEx; FormMy, LV : HWND; MMsg: Msg; XScreen, YScreen : Integer;
implementation
var FormRect : TRect;
iHeight, iPos, iRet : Integer; hDragImageList : HIMAGELIST; hOneImageList, hTempImageList : HIMAGELIST; bDragging, bFirst : BOOL; lvhti : tLVHITTESTINFO; imf : IMAGEINFO; Item : TLVItem; P, pt : TPoint; Buf : array [0..MAX_PATH] of Char;
Const LVID = 13;
Function WinProc(Wnd: HWND; Msg : UINT; WParam : WPARAM; LParam: LPARAM): lresult; Stdcall; Var lvc : TLVColumn; I, B : Integer;
Begin Result := 0; Case Msg Of WM_CREATE: begin
LV := CreateWindowEx(WS_EX_CLIENTEDGE,'SysListView32', '1', WS_CHILD or WS_VISIBLE or LVS_REPORT or LVS_SHOWSELALWAYS , 0, 0, FormRect.Right, FormRect.Bottom,Wnd, LVID, HInstance, nil);
SendMessage(lv, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, LVS_EX_DOUBLEBUFFER or LVS_EX_HEADERDRAGDROP or LVS_EX_BORDERSELECT or LVS_EX_FULLROWSELECT or LVS_EX_GRIDLINES or LVS_EX_INFOTIP); SendMessage(LV, LVM_SETTEXTBKCOLOR, 0, 12632256); SendMessage(LV, LVM_SETBKCOLOR, 0, 12632256);
lvc.fmt := LVCFMT_CENTER; lvc.mask := LVCF_TEXT or LVCF_WIDTH; lvc.pszText := '0'; lvc.cx := 70; lvc.iSubItem := 0; ListView_InsertColumn(lv, 0, lvc);
lvc.mask := lvc.mask or LVCF_FMT or LVCF_SUBITEM or LVCF_ORDER;
for I := 1 to 7 do begin lvc.pszText := PChar(IntToStr(I)); lvc.iSubItem := I; lvc.iOrder := I; ListView_InsertColumn(LV, I, lvc); end;
for I := 0 to 6 do begin FillChar(Item, sizeof(Item), 0 ); Item.mask := LVIF_TEXT; Item.stateMask := LVIS_DROPHILITED; Item.iItem := ListView_GetItemCount(LV); Item.pszText := PChar(IntToStr(I)); ListView_InsertItem(LV, Item); for b := 0 to {Header_GetItemCount(ListView_GetHeader(LV)) -2}6 do begin Item.iSubItem := B + 1; Item.pszText := PChar(IntToStr(Random(100))); ListView_SetItem(LV, Item); end; end; end; WM_MOUSEMOVE: begin if not bDragging then Exit;
p.x := LOWORD(lParam); p.y := HIWORD(lParam); ImageList_DragMove(p.x, p.y);
Exit; end; WM_NOTIFY: begin if PNMHDR(lParam).hwndFrom = LV then case PNMHDR(lParam).code of LVN_BEGINDRAG: begin p.x := 8; p.y := 8;
bFirst := TRUE; iPos := ListView_GetNextItem(LV, -1, LVNI_SELECTED); while (iPos <> -1) do begin if bFirst then begin hDragImageList := ListView_CreateDragImage(LV, iPos, p); ImageList_GetImageInfo(hDragImageList, 0, imf); iHeight := imf.rcImage.Bottom; bFirst := FALSE; end else begin hOneImageList := ListView_CreateDragImage(LV, iPos, p); hTempImageList := ImageList_Merge(hDragImageList, 0, hOneImageList, 0, 0, iHeight); ImageList_Destroy(hDragImageList); ImageList_Destroy(hOneImageList); hDragImageList := hTempImageList; ImageList_GetImageInfo(hDragImageList, 0, imf); iHeight := imf.rcImage.bottom; end;
iPos := ListView_GetNextItem(LV, iPos, LVNI_SELECTED);
end; ImageList_BeginDrag(hDragImageList, 0, 0, 0);
pt := PNMListView(LParam).ptAction;
ImageList_DragEnter({GetDesktopWindow()} LV, pt.x, pt.y);
bDragging := TRUE; SetCapture(Wnd); Exit; end; end; end;
WM_LBUTTONUP: begin bDragging := FALSE; ImageList_DragLeave(LV); ImageList_EndDrag(); ImageList_Destroy(hDragImageList);
ReleaseCapture();
FillChar(lvhti, sizeof(lvhti), 0 ); lvhti.pt.x := LOWORD(lParam); lvhti.pt.y := HIWORD(lParam); ClientToScreen(Wnd, lvhti.pt); ScreenToClient(LV, lvhti.pt); ListView_HitTest(LV, lvhti);
if lvhti.iItem = -1 then Exit; if ((lvhti.flags and LVHT_ONITEMLABEL = 0) and (lvhti.flags and LVHT_ONITEMSTATEICON = 0)) then Exit; FillChar(Item, sizeof(Item), 0 );
Item.iItem := lvhti.iItem; Item.iSubItem := 0; Item.mask := LVIF_STATE; Item.stateMask := LVIS_SELECTED; ListView_GetItem(LV, Item);
if (Item.state = LVIS_SELECTED) then Exit;
iPos := ListView_GetNextItem(LV, -1, LVNI_SELECTED); // while iPos <> -1 do begin // First, copy one item FillChar(Item, sizeof(Item), 0 ); Item.iItem := iPos; Item.iSubItem := 0; Item.cchTextMax := MAX_PATH; Item.pszText := buf; Item.stateMask := LVIS_SELECTED; Item.mask := LVIF_STATE or LVIF_IMAGE or LVIF_INDENT or LVIF_PARAM or LVIF_TEXT; ListView_GetItem(lv, Item); Item.iItem := lvhti.iItem; // Вставьте пункт главного iRet := ListView_InsertItem(LV, Item); if Item.iItem < iPos then inc(lvhti.iItem) ;
if (iRet <= iPos) then inc(iPos);
for i := 0 to 7 do begin ListView_GetItemText(lv, iPos, i, buf, SizeOf(Buf)); ListView_SetItemText(LV, iRet, i, buf); end; ListView_DeleteItem(LV, iPos); iPos := ListView_GetNextItem(LV, -1, LVNI_SELECTED); // Break; end;
Exit; end;
WM_SIZE: Begin GetClientRect(Wnd, FormRect); SetWindowPos(LV, 0, 0, 0, FormRect.Right, FormRect.Bottom - 50, SWP_NOZORDER); End;
WM_CLOSE: begin DestroyWindow(LV); DestroyWindow(Wnd); end;
WM_DESTROY: PostQuitMessage(0); Else Result := DefWindowProc(Wnd, Msg, WParam, LParam); End; End;
-
Есть кто живой?
|