Суть бага: API ф-ция CreateWindowEx (в дельфи 6, проверил на 2 компах) отказывается создавать окна класса 'SysListView32', если к проекту не подключёна одна из следующих либ: forms\menus\controls\ImgList. (а если точнее - любая, цепляющая за собой controls.pas) Пример (30 строк), в котором убирая комменты можно создать окно любого класса, кроме 'SysListView32'. 'SysListView32' удастся создать в случае, если раскомментировать последнюю строку. (при этом параметр, передаваемый ф-ции ImageList_DragLeave значения не имеет. Ведь она никогда не выполнится. Рекурсия. Брейнфак.) Code: program test_unit; uses windows, Types, commctrl, classes, sysutils; {$APPTYPE CONSOLE} var handle_of_this_program:HWND; msg:TMSG; i:integer; begin handle_of_this_program := GetModuleHandle(nil); CreateWindowEx(0,'SysListView32', Pchar('title'),WS_VISIBLE or LVS_REPORT or LVS_EDITLABELS or LVS_SHOWSELALWAYS or LVS_SHAREIMAGELISTS or LVS_OWNERDATA,0, 0, 600, 400, 0, 0,handle_of_this_program,nil); // CreateWindowEx(0,'SysListView32', Pchar('title'),WS_VISIBLE ,0, 0, 600, 400, 0, 0,handle_of_this_program,nil); // CreateWindowEx(0,'BUTTON', Pchar('title'),WS_VISIBLE ,0, 0, 600, 400, 0, 0,handle_of_this_program,nil); // CreateWindowEx(0,'EDIT', Pchar('title'),WS_VISIBLE ,0, 0, 600, 400, 0, 0,handle_of_this_program,nil); // CreateWindowEx(0,'COMBOBOX', Pchar('title'),WS_VISIBLE ,0, 0, 600, 400, 0, 0,handle_of_this_program,nil); // CreateWindowEx(0,'LISTBOX', Pchar('title'),WS_VISIBLE ,0, 0, 600, 400, 0, 0,handle_of_this_program,nil); // CreateWindowEx(0,'STATIC', Pchar('title'),WS_VISIBLE ,0, 0, 600, 400, 0, 0,handle_of_this_program,nil); // CreateWindowEx(0,'SCROLLBAR', Pchar('title'),WS_VISIBLE ,0, 0, 600, 400, 0, 0,handle_of_this_program,nil); while GetMessage(Msg, 0, 0, 0) do begin TranslateMessage(Msg); DispatchMessage(Msg); end; // if i=strtoint('это условие выполнится, когда рак на горе свистнет') then ImageList_DragLeave(i); end. Дли чистоты эксперимента, то же самое, написанное без использования библиотек: Code: program test_unit; {$APPTYPE CONSOLE} type HWND = type LongWord; UINT = type LongWord; WPARAM = Longint; LPARAM = Longint; DWORD = LongWord; HMENU = type LongWord; BOOL = LongBool; LRESULT = Longint; TPoint = packed record X: Longint; Y: Longint; end; tMSG = packed record hwnd: HWND; message: UINT; wParam: WPARAM; lParam: LPARAM; time: DWORD; pt: TPoint; end; const WS_VISIBLE = $10000000; var handle_of_this_program:HWND; msg:TMSG; //сообщение ф-ции GetMessage hlv:HWND; //хэндл листвью i:integer; //API ф-ции, чтобы не подключать никаких либ function CreateWindowEx(dwExStyle: DWORD; lpClassName: PChar; lpWindowName: PChar; dwStyle: DWORD; X, Y, nWidth, nHeight: Integer; hWndParent: HWND; hMenu: HMENU; hInstance: HINST; lpParam: Pointer): HWND; stdcall; external 'user32.dll' name 'CreateWindowExA'; function GetModuleHandle(lpModuleName: PChar): HMODULE; stdcall; external 'kernel32.dll' name 'GetModuleHandleA'; function GetMessage(var lpMsg: TMsg; hWnd: HWND; wMsgFilterMin, wMsgFilterMax: UINT): BOOL; stdcall; external 'user32.dll' name 'GetMessageA'; function TranslateMessage(const lpMsg: TMsg): BOOL; stdcall; external 'user32.dll' name 'TranslateMessage'; function DispatchMessage(const lpMsg: TMsg): Longint; stdcall; external 'user32.dll' name 'DispatchMessageA'; function SendMessage(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall; external 'user32.dll' name 'SendMessageA'; function ImageList_DragLeave(LockWnd: HWnd): Bool; stdcall; external 'comctl32.dll' name 'ImageList_DragLeave'; begin handle_of_this_program := GetModuleHandle(nil); //получаем хендл программы чтобы создать окно //листвью "по-минимуму". пока последня строка раскомментирована - создается. hlv:=CreateWindowEx(0,'SysListView32', Pchar('title'),WS_VISIBLE ,0, 0, 600, 400, 0, 0,handle_of_this_program,nil); //пример с обычной кнопкой. Создается как положено //hlv:=CreateWindowEx(0,'button', Pchar('title'),WS_VISIBLE,0, 0, 600, 400, 0, 0,handle_of_this_program,nil); while GetMessage(Msg, 0, 0, 0) do begin TranslateMessage(Msg); DispatchMessage(Msg); end; if (i-1)=(i+1) then ImageList_DragLeave(i); end. ps. Столкнулся случайно, когда писал сурс-образец, иллюстрирующий другую ошибку 'SysListView32', с сообщениями LVM_SETCOLUMNORDERARRAY\LVM_GETCOLUMNORDERARRAY. Убил 6 часов на поиски причины. Может кому пригодится
Нет, на баг не похоже. Не понимаю, в чем причина такого долгого поиска решения проблемы. Если считаешь, что каким то боком тут виновен controls.pas, то просто посмотри что происходит в этом модуле в секциях initialization/finalization. Если окно не создается, то нужно посмотреть код ошибки, многое может сказать. Еще стоит взглянуть в модуль ComCtrls, вроде как этот SysListView32 как раз там используется, ну и вообщем как это все в VCL делается. Да и кстати Code: handle_of_this_program:HWND; Ух, можно было конкретизировать Code: handle_of_this_program_running_on_the_current_computer : HWND;
Jingo контролс.пас виновен только тем, что в одной из функций, имеющей глубокую вложенность и принадлежность к формам, может быть вызвана Api ф-ция, к-рую я нашел. (но если не использовать дельфиевский дрэглист, то выполнена она не будет) К тестовому сурсу что я написал можно добавить свой "тестовый_сурс_2", и в нём написать ф-цию, которая будет вызывать ImageList_DragLeave(123); В первом тестовом сурсе эту функцию ты вызывать не будешь, но листвью начнет появляться. Точно такая же стиуация с контролс.пас. Я удалил его инициализацию, а затем - все до одного типы и функции (сначала проделав то же самое с формс.пас), пока не обнаружил то, что заставляло листвью появляться. А ошибка при неудачном создании листвью такая: Error 1407: Cannot find window class
Code: program test; uses Windows, SysUtils, Messages, commctrl; {$EXTERNALSYM InitCommonControls} procedure InitCommonControls; external comctl32 name 'InitCommonControls'; var Instance: HWnd; wClass: TWndClass; Handle, hListView: HWnd; msg: TMsg; col: LV_COLUMN; pItem: TLVItem; dwStyle, i: DWORD; //Процедура выхода из программы procedure DoExit; begin Halt; end; function WindowProc (Hwn,msg,wpr,lpr: longint): longint; stdcall; begin result:= defwindowproc(hwn,msg,wpr,lpr); if msg = WM_DESTROY then DoExit; if msg = WM_KEYDOWN then if wpr = VK_ESCAPE then DoExit; end; begin InitCommonControls; Instance:= GetModuleHandle(nil); wClass.style:= CS_HREDRAW or CS_VREDRAW or CS_CLASSDC; wClass.Lpfnwndproc:= @windowproc; wClass.Hinstance:= Instance; wClass.HbrBackground:= COLOR_BACKGROUND; wClass.LpszClassName:= 'DX'; wClass.Hcursor:= LoadCursor(0,IDC_ARROW); RegisterClass(wClass); Handle:= CreateWindowEx(WS_EX_WINDOWEDGE, 'DX', 'window', $14CF0000, CW_USEDEFAULT, CW_USEDEFAULT, 400, 300, 0, 0, Instance, nil); ShowWindow(Handle, SW_SHOW); UpdateWindow(Handle); hListView:= CreateWindowEx(WS_EX_CLIENTEDGE, 'SysListView32', '', WS_CHILD or WS_VISIBLE or LVS_REPORT or LVS_EDITLABELS or LVS_SHOWSELALWAYS, 0, 0, 400, 300, Handle, 0, Instance, nil); col.mask:= LVCF_FMT or LVCF_WIDTH or LVCF_TEXT or LVCF_SUBITEM; col.fmt:= LVCFMT_LEFT; col.cx:= 150; col.iSubItem:= 0; col.pszText:= LPSTR('Column 0'); ListView_InsertColumn(hListView, 0, col); dwStyle:= ListView_GetExtendedListViewStyle(hListView); dwStyle:= dwStyle or LVS_EX_GRIDLINES; ListView_SetExtendedListViewStyle(hListView, dwStyle); pItem.mask:= LVIF_TEXT; pItem.iSubItem:= 0; for i:= 0 to 5 do begin pItem.pszText:= LPSTR('Item ' + IntToStr(i)); pItem.iItem:= i; ListView_InsertItem(hListView, pItem); end; while (GetMessage(msg, 0, 0, 0)) do begin translatemessage(msg); dispatchmessage(msg); end; end. Что я делаю не так?