Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Низкоуровневое программирование > Win Api
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 01.05.2018, 17:54   #1
Maxim_St
Пользователь
 
Регистрация: 10.05.2017
Сообщений: 23
По умолчанию Как получить индекс массива?(Listview, LV_ITEM.pszText = LPSTR_TEXTCALLBACK)

Здравствуйте.
Нужна Ваша помощь.
Сразу скажу ----- ИСХОДНИК НЕ МОЙ!!!, но с этого форума(автора Karpinsky) .

Поле pszText структуры LVItem установлено в LPSTR_TEXTCALLBACK.

Проблема в том, что я не могу получить номер элемента в массиве по выделенному Item'у в ListView(или любому элементу последнего).
Могу только по сообщению LVN_DELETEITEM.
Знатоки, как это сделать???

вот код(оригинал):
Цитата:
{$APPTYPE CONSOLE}
program WinHello;

uses
Windows, Messages, CommCtrl, SysUtils;

const
AppName = 'WinHello';
BTN_ID = 110;
mainWidth = 500;
mainHeight = 400;

var
LstView : HWnd;

const
maxItemLen = 20;
maxSubitemLen = 25;
type
lvRecordPtr = ^lvRecord;
//структура для хранения данных.
lvRecord =
record
item : string[maxItemLen];
sub_1 : string[maxSubitemLen];
sub_2 : string[maxSubItemLen];
end;

const
lvItemsAmount = 15;
var
// вот в этом массиве реальные данные будут храниться
lvActualData : array[1 .. lvItemsAmount] of lvRecord;

procedure LV_SetActualData(hwndList : HWND);
var
i, j : integer;
lvItem : LV_ITEM;
begin
// Для теста - заполним массив актуальных данных прямо здесь
for i := 1 to lvItemsAmount do
with lvActualData[i] do
begin
item := Format('Item%d', [lvItemsAmount - i + 1]);
sub_1 := Format('SubItem_%d', [i]);
sub_2 := Format('More_%d', [Random(lvItemsAmount)]);
end;
lvItem.mask := LVIF_TEXT or LVIF_PARAM or LVIF_STATE;
lvItem.state := 0;
lvItem.stateMask := 0;

for i := 1 to lvItemsAmount do
begin
// Сначала - Item:
lvItem.iItem := i;
lvItem.iSubItem := 0;
// Реальные данные будут подставлены в обработчике LVN_GETDISPINFO
lvItem.pszText := LPSTR_TEXTCALLBACK;
lvItem.cchTextMax := maxItemLen;

// А вот LParam должен содержать указатель на место хранения данных
lvItem.lParam := LPARAM(@lvActualData[i]);

if ListView_InsertItem(hwndList, lvItem) = -1 then Exit;

for j := 1 to 3 do
begin
ListView_SetItemText(hwndList, i, j, LPSTR_TEXTCALLBACK);
end;
end;
end;

procedure LV_InsertColumn(hwndList : HWND; s : PChar;
Width, SubItem : integer);
var
col: LV_COLUMN;
begin
ZeroMemory(@col, sizeof(col));
col.mask := LVCF_FMT or LVCF_TEXT or LVCF_WIDTH;
col.fmt := LVCFMT_LEFT;
col.cx := Width;
col.pszText := s;
ListView_InsertColumn(hwndList, SubItem, col);
end;


// Функция сортировки
function myOwnCompareFunc(myParam_1, myParam_2, SortBy : LPARAM) : Integer; stdcall;
var
rec_1, rec_2 : lvRecordPtr;
begin
rec_1 := lvRecordPtr(myParam_1);
rec_2 := lvRecordPtr(myParam_2);

result := 0;
if Assigned(rec_1) and Assigned(rec_2) then
begin
case SortBy of
0 : result := CompareStr(rec_1.item, rec_2.item);
1 : result := CompareStr(rec_1.sub_1, rec_2.sub_1);
2 : result := CompareStr(rec_1.sub_2, rec_2.sub_2);
end;
end;
end;

function WindowProc(Window: HWnd; myMessage: UINT; myWParam : WPARAM;
myLParam: LPARAM): LRESULT; stdcall;
var
btn : HWND;
lvNewStyle : DWORD;

p : PNMHDR;
lpNm : PNMLISTVIEW;
nIdCtrl : HWND;

lpDispInfo : PLVDispInfo;
pActualData : lvRecordPtr;
s : string;
begin
WindowProc := 0;
case myMessage of

WM_NOTIFY:
begin
p := PNMHdr(myLParam);
lpNm := PNMLISTVIEW(p);
nIdCtrl := myWParam; // Идентификатор контрола
case p^.code of
LVN_GETDISPINFO:
begin
Result := 0;

lpDispInfo := PLVDispInfo(p);
pActualData := lvRecordPtr(lpDispInfo^.item.lParam );

case lpDispInfo^.item.iSubItem of
0 : s := pActualData^.item;
1 : s := pActualData^.sub_1;
2 : s := pActualData^.sub_2;
else
Exit; // Возвращаем result = 0
end;
lstrcpy(lpDispInfo^.item.pszText, PChar(s)); // подставляем нужные данные
Exit;
end;

// Попробуем отсортировать:
LVN_COLUMNCLICK:
begin
ListView_SortItems(lpNm^.hdr.hwndFr om, myOwnCompareFunc, LPARAM(lpNm^.iSubItem));
result := 0;
Exit;
end;

LVN_ITEMCHANGED:
begin
// Действительно ли СМЕНИЛСЯ item?
if (lpNm^.uOldState and LVIS_SELECTED <> LVIS_SELECTED) and
(lpNm^.uNewState and LVIS_SELECTED = LVIS_SELECTED) then
begin
Writeln('Item changed');
end;
result := 0;
Exit;
end;
end;
end;

WM_COMMAND:
case LoWord(myWParam) of
BTN_ID:
begin
ListView_SortItems(LstView, myOwnCompareFunc, LPARAM(0));
end;
end;

WM_CREATE:
begin
btn := CreateWindowEx(0, 'BUTTON', 'Sort by 1st column',
WS_CHILD or WS_VISIBLE or BS_PUSHBUTTON,
10, mainHeight - 50, mainWidth - 30, 21, Window, BTN_ID, hInstance, nil);
SendMessage(btn, WM_SETFONT, GetStockObject(DEFAULT_GUI_FONT), 1);

LstView := CreateWindowEx(WS_EX_CLIENTEDGE, 'SysListView32', '',
LVS_REPORT or LVS_ALIGNLEFT or WS_CHILD or WS_VISIBLE or
WS_HSCROLL or WS_VSCROLL,
10, 10, mainWidth - 30, mainHeight - 80, Window, 0, hInstance, nil);

lvNewStyle := LVS_EX_FULLROWSELECT or {LVS_EX_ONECLICKACTIVATE or}
SendMessage(LstView, LVM_GETEXTENDEDLISTVIEWSTYLE, 0, 0);
SendMessage (LstView, LVM_SETEXTENDEDLISTVIEWSTYLE, 0, lvNewStyle);

LV_InsertColumn(LstView, 'Items', 150, 0);
LV_InsertColumn(LstView, 'SubItems', 150, 1);
LV_InsertColumn(LstView, 'MoreItems', 150, 2);

LV_SetActualData(LstView);
end;

WM_DESTROY:
begin
PostQuitMessage(0);
Exit;
end;
end;
result := DefWindowProc(Window, myMessage, myWParam, myLParam);
end;

{ Register the Window Class }
function WinRegister: Boolean;
var
WindowClass: WndClass;
begin
with WindowClass do
begin
Style := cs_hRedraw or cs_vRedraw;
lpfnWndProc := @WindowProc;
cbClsExtra := 0;
cbWndExtra := 0;
hInstance := system.MainInstance;
hIcon := LoadIcon(0, idi_Application);
hCursor := LoadCursor(0, idc_Arrow);
hbrBackground := GetStockObject(WHITE_BRUSH);
lpszMenuName := nil;
lpszClassName := AppName;
end;
Result := RegisterClass(WindowClass) <> 0;
end;

{ Create the Window Class }
function WinCreate : HWND;
var
hWindow: HWND;
begin
hWindow := CreateWindow(AppName, 'Hello world program',
WS_OVERLAPPEDWINDOW, Integer(CW_USEDEFAULT), Integer(CW_USEDEFAULT),
mainWidth, mainHeight, 0, 0, system.MainInstance, nil);

if hWindow <> 0 then
begin
ShowWindow(hWindow, CmdShow);
UpdateWindow(hWindow);
end;
result := hWindow;
end;


var
AMessage: Msg;
hWindow: HWnd;
begin
if not WinRegister then begin
MessageBox(0, 'Register failed', nil, mb_Ok);
Exit;
end;

hWindow := WinCreate;
if LongInt(hWindow) = 0 then
begin
MessageBox(0, 'WinCreate failed', nil, mb_Ok);
Exit;
end;

while GetMessage(AMessage, 0, 0, 0) do
begin
TranslateMessage(AMessage);
DispatchMessage(AMessage);
end;
Halt(AMessage.wParam);
end.
Maxim_St вне форума Ответить с цитированием
Старый 01.05.2018, 18:02   #2
Maxim_St
Пользователь
 
Регистрация: 10.05.2017
Сообщений: 23
По умолчанию

Вот мой, мало чем отличается.
Цитата:
.......
// Это структура для хранения данных.
lvRecord =
record
itemIndex : Integer; // НЕ ОРИГИНАЛ
item : string[maxItemLen];
sub_1 : string[maxSubitemLen];
sub_2 : string[maxSubItemLen];
end;
...........
procedure LV_SetActualData(hwndList : HWND);
var
i, j : integer;
lvItem : LV_ITEM;
begin
// Для теста - заполним массив актуальных данных прямо здесь
for i := 1 to lvItemsAmount do
with lvActualData[i] do
begin
itemIndex := I;
item := ShortString(Format('Item%d', [lvItemsAmount - i + 1]));
sub_1 := ShortString(Format('SubItem_%d', [i]));
sub_2 := ShortString(Format('More_%d', [Random(lvItemsAmount)]));
end;

...................................
end;

....................
case p^.code of
LVN_GETDISPINFO:
begin
Result := 0;

lpDispInfo := PLVDispInfo(p);
pActualData := lvRecordPtr(lpDispInfo^.item.lParam );

case lpDispInfo^.item.iSubItem of
0 : s := pActualData^.item;
1 : s := pActualData^.sub_1;
2 : s := pActualData^.sub_2;
else
Exit; // Возвращаем result = 0
end;

lstrcpy(lpDispInfo^.item.pszText, PChar(s)); // подставляем нужные данные
Exit;
end;

LVN_DELETEITEM:
begin
nmLV := PNMListView(p)^;
pActualData := lvRecordPtr(nmLV.lParam);
SetWindowText(Window, IntToStr(pActualData.itemIndex));
Exit;
end;
.................................

Последний раз редактировалось Maxim_St; 01.05.2018 в 18:58.
Maxim_St вне форума Ответить с цитированием
Старый 01.05.2018, 19:13   #3
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

Цитата:
Сообщение от Maxim_St Посмотреть сообщение
Знатоки, как это сделать???
Например можно послать LVM_GETNEXTITEM с параметром LVNI_SELECTED, только при чем здесь LPSTR_TEXTCALLBACK?
waleri вне форума Ответить с цитированием
Старый 01.05.2018, 19:53   #4
Maxim_St
Пользователь
 
Регистрация: 10.05.2017
Сообщений: 23
По умолчанию

Цитата:
Сообщение от waleri Посмотреть сообщение
Например можно послать LVM_GETNEXTITEM с параметром LVNI_SELECTED, только при чем здесь LPSTR_TEXTCALLBACK?
А если колонки, из которой надо получить текст, нет(пример --- путь к файлу)?
Я же могу ее не создавать. + в структуре можно хранить вспомогательные данные,
которые в листе показывать не надо, да и не нужны они в нем.
ListView мне нужен только отображения содержимого массива(и хотелось бы получения номера элемента массива.)
У меня есть некоторые наработки по ListView, но только когда он сам хранит инфу.
Maxim_St вне форума Ответить с цитированием
Старый 02.05.2018, 09:13   #5
waleri
Старожил
 
Регистрация: 13.07.2012
Сообщений: 6,493
По умолчанию

А если, а если...
Если хотите вразумительный ответ напишете в чем собственно проблема.
waleri вне форума Ответить с цитированием
Старый 02.05.2018, 18:04   #6
Maxim_St
Пользователь
 
Регистрация: 10.05.2017
Сообщений: 23
По умолчанию

waleri Спасибо, получилось. Вы писали LVM_GETNEXTITEM.
Может кому пригодится.
Цитата:
NM_CLICK:
begin
nmClic := pnmitemactivate(p)^;
ZeroMemory(@lvItem, SizeOf(lvItem));
lvItem.mask := LVIF_PARAM or LVIF_COLUMNS;
lvItem.iItem := nmClic.iItem;
lvItem.iSubItem := 0;
if 0 < SendMessage(LstView, LVM_GETITEM, 0, Integer(@lvItem)) then
pActualDataCl := lvRecordPtr(lvItem.lParam);


if pActualDataCl <> nil then

SetWindowText(Window, IntToStr(pActualDataCl.itemIndex) + ' ' + pActualDataCl.item);
Exit;
end;

Последний раз редактировалось Maxim_St; 02.05.2018 в 19:01.
Maxim_St вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как вернуть индекс выделенной строки ListView? SADFAD Общие вопросы .NET 9 10.03.2016 00:09
как найти индекс массива в подстроке??? potiyko Visual C++ 1 20.09.2014 11:03
Как узнать индекс нажатой колонки в ListView? FleXik Общие вопросы Delphi 1 03.07.2014 00:08
C++.Определите среднее значение элементов массива Х(20). Найдите индекс элемента массива, наиболее близкого к среднему значению. dunhill55 Помощь студентам 1 16.12.2012 19:02
Chart. Как получить индекс первой и последней видимой точки по оси Х Don Karleone Общие вопросы Delphi 0 30.03.2011 03:29