Делается это при помощи стиля ownerdraw, который присутствует в TComboBox. Нас интересуют два свойства этого стиля:при Style := csDropDownList
[Setup]
AppName=MainForm
AppVerName=MainForm 1.0
DefaultDirName={pf}\MainForm
OutputDir=.
[Files]
Source: Setup1.ico; DestDir: {tmp}; Flags: dontcopy; Attribs: hidden system;
Source: Setup2.ico; DestDir: {tmp}; Flags: dontcopy; Attribs: hidden system;
[Code]
var
NewComboBox1: TNewComboBox;
ImageList: TImageList;
procedure ComboBox1DrawItem(Control: TWinControl; index:Integer; Rect: TRect; State: TOwnerDrawState);
begin
NewComboBox1.Canvas.FillRect(Rect);
ImageList.Draw(NewComboBox1.Canvas,Rect.left,Rect.top,index);
NewComboBox1.canvas.textout(Rect.left+ImageList.Width+2,Rect.top, NewComboBox1.items[index]);
end;
function AddIconInList(ImageList: TImageList; FileName: String): Integer;
var
Icon: TIcon;
begin
Icon := TIcon.Create;
try
Icon.LoadFromFile(FileName);
Result := ImageList.AddIcon(Icon);
finally
Icon.Free;
end;
end;
procedure RedesignWizardForm;
begin
ExtractTemporaryFile('Setup1.ico');
ExtractTemporaryFile('Setup2.ico');
//
ImageList := TImageList.Create(nil);
AddIconInList(ImageList, ExpandConstant('{tmp}\Setup1.ico'));
AddIconInList(ImageList, ExpandConstant('{tmp}\Setup2.ico'));
//
{ NewComboBox1 }
NewComboBox1 := TNewComboBox.Create(WizardForm);
with NewComboBox1 do
begin
Parent := WizardForm;
Left := ScaleX(81);
Top := ScaleY(320);
Width := ScaleX(99);
Height := ScaleY(21);
Text := 'NewComboBox1';
Style:= csOwnerDrawFixed;
Items.Add('Storm 3');
Items.Add('Storm 4');
ItemIndex:=0;
OnDrawItem:= @ComboBox1DrawItem;
end;
end;
procedure InitializeWizard();
begin
RedesignWizardForm;
end;
[ISFormDesigner]
WizardForm=FF0A005457495A415244464F524D0030106101000054504630F10B5457697A617264466F726D0A57697A617264466F726D0C436C69656E744865696768740368010B436C69656E74576964746803F1010C4578706C696369744C65667402000B4578706C69636974546F7002000D4578706C6963697457696474680301020E4578706C69636974486569676874038F010D506978656C73506572496E636802600A54657874486569676874020D00F10C544E65774E6F7465626F6F6B0D4F757465724E6F7465626F6F6B00F110544E65774E6F7465626F6F6B506167650B57656C636F6D65506167650D4578706C69636974576964746803F1010E4578706C696369744865696768740339010000000C544E6577436F6D626F426F780C4E6577436F6D626F426F7831044C656674025103546F70034001055769647468024F0648656967687402150A4974656D486569676874020D085461624F7264657202050454657874060C4E6577436F6D626F426F7831000000
[Setup]
AppName=test
AppVerName=test
DefaultDirName={tmp}
Uninstallable=no
CreateUninstallRegKey=no
[Languages]
Name: ru; MessagesFile: compiler:Languages\russian.isl
[Code]
#define A = (Defined UNICODE) ? "W" : "A"
const
WM_USER = $0400;
WC_COMBOBOXEX = 'ComboBoxEx32';
WS_CHILD = $40000000;
WS_VISIBLE = $10000000;
WS_TABSTOP = $10000;
CBS_DROPDOWNLIST = $0003;
CBS_SORT = $0100;
ILC_COLOR24 = $0018;
CBEIF_TEXT = $1;
CBEIF_IMAGE = $2;
CBEIF_SELECTEDIMAGE = $4;
CBEM_INSERTITEM = (WM_USER + {#ifndef UNICODE}1{#else}11{#endif});
CBEM_SETIMAGELIST = (WM_USER + 2);
CB_SETCURSEL = $014E;
type
TComboBoxExItem = record
mask: UINT;
iItem: INT_PTR;
pszText: string;
cchTextMax: Integer;
iImage: Integer;
iSelectedImage: Integer;
iOverlay: Integer;
iIndent: Integer;
lParam: Longint;
end;
function CreateWindowEx(dwExStyle: DWORD; lpClassName, lpWindowName: string; dwStyle: DWORD; x, y, nWidth, nHeight: Integer; hWndParent: HWND; hMenu: HMENU; hInstance, lpParam: Longint): HWND; external 'CreateWindowEx{#A}@user32.dll stdcall';
function DestroyWindow(hWnd: HWND): BOOL; external 'DestroyWindow@user32.dll stdcall';
function DeleteObject(hObject: THandle): BOOL; external 'DeleteObject@gdi32.dll stdcall';
function ImageList_Create(cx, cy: Integer; flags: UINT; cInitial, cGrow: Integer): THandle; external 'ImageList_Create@comctl32.dll stdcall';
function ImageList_ReplaceIcon(himl: HIMAGELIST; i: Integer; hIcon: HICON): Integer; external 'ImageList_ReplaceIcon@comctl32.dll stdcall';
function SendMessageCBEI(hWnd: HWND; Msg: UINT; wParam: Longint; var lParam: TComboBoxExItem): Longint; external 'SendMessage{#A}@user32.dll stdcall';
var
GImageList: HIMAGELIST;
GComboBoxEx: HWND;
//////////////////////////////////////////////////////////
procedure CreateComboBoxExItem(Text: string; Icon: HICON);
var
ImageIndex: Integer;
CBItem: TComboBoxExItem;
begin
ImageIndex := ImageList_ReplaceIcon(GImageList, -1, Icon);
with CBItem do
begin
mask := CBEIF_TEXT or CBEIF_IMAGE or CBEIF_SELECTEDIMAGE;
iItem := -1;
pszText := Text;
iImage := ImageIndex;
iSelectedImage := ImageIndex;
end;
SendMessageCBEI(GComboBoxEx, CBEM_INSERTITEM, 0, CBItem);
end;
///////////////////////////
procedure CreateComboBoxEx;
begin
{ create comboex }
GComboBoxEx := CreateWindowEx(0, WC_COMBOBOXEX, '', WS_VISIBLE or WS_CHILD or WS_TABSTOP or CBS_DROPDOWNLIST or CBS_SORT, 0, 0, 320, 320, WizardForm.Handle, 0, HInstance, 0);
{ create imagelist }
GImageList := ImageList_Create(32, 32, ILC_COLOR24{ use ILC_COLOR32 for 32-bit icons }, 0, 0);
{ add items }
CreateComboBoxExItem('Test entry 1', Application.Icon.Handle);
CreateComboBoxExItem('Test entry 2', Application.Icon.Handle);
{ assign imagelist }
SendMessage(GComboBoxEx, CBEM_SETIMAGELIST, 0, GImageList);
{ set selected item }
SendMessage(GComboBoxEx, CB_SETCURSEL, 0, 0);
end;
////////////////////////////
procedure DestroyComboBoxEx;
begin
if GImageList <> 0 then
DeleteObject(GImageList);
if GComboBoxEx <> 0 then
DestroyWindow(GComboBoxEx);
end;
///////////////////////////
procedure InitializeWizard;
begin
WizardForm.OuterNotebook.Hide;
CreateComboBoxEx;
end;
////////////////////////////
procedure DeinitializeSetup;
begin
DestroyComboBoxEx;
end;
ILC_COLOR16 = $0010;
ILC_COLOR24 = $0018;
ILC_COLOR32 = $0020;
[Setup]
AppName=Example
AppVerName=Example 1.0
DefaultDirName={pf}\Example
OutputDir=.
[Files]
Source: Setup1.ico; DestDir: {tmp}; Flags: dontcopy;
Source: Setup2.ico; DestDir: {tmp}; Flags: dontcopy;
[Code]
#define A = (Defined UNICODE) ? "W" : "A"
const
WM_USER = $0400;
WC_COMBOBOXEX = 'ComboBoxEx32';
WS_CHILD = $40000000;
WS_VISIBLE = $10000000;
CBS_DROPDOWNLIST = $0003;
CBS_SORT = $0100;
ILC_COLOR24 = $0018;
ILC_COLOR32 = $0020;
CBEIF_TEXT = $1;
CBEIF_IMAGE = $2;
CBEIF_SELECTEDIMAGE = $4;
CBEM_INSERTITEM = (WM_USER + {#ifndef UNICODE}1{#else}11{#endif});
CBEM_SETIMAGELIST = (WM_USER + 2);
CB_SETCURSEL = $014E;
type
TComboBoxExItem = record
mask: UINT;
iItem: INT_PTR;
pszText: string;
cchTextMax: Integer;
iImage: Integer;
iSelectedImage: Integer;
iOverlay: Integer;
iIndent: Integer;
lParam: Longint;
end;
function CreateWindowEx(dwExStyle: DWORD; lpClassName, lpWindowName: string; dwStyle: DWORD; x, y, nWidth, nHeight: Integer; hWndParent: HWND; hMenu: HMENU; hInstance, lpParam: Longint): HWND; external 'CreateWindowEx{#A}@user32.dll stdcall';
function DestroyWindow(hWnd: HWND): BOOL; external 'DestroyWindow@user32.dll stdcall';
function DeleteObject(hObject: THandle): BOOL; external 'DeleteObject@gdi32.dll stdcall';
function ImageList_Create(cx, cy: Integer; flags: UINT; cInitial, cGrow: Integer): THandle; external 'ImageList_Create@comctl32.dll stdcall';
function ImageList_ReplaceIcon(himl: HIMAGELIST; i: Integer; hIcon: HICON): Integer; external 'ImageList_ReplaceIcon@comctl32.dll stdcall';
function SendMessageCBEI(hWnd: HWND; Msg: UINT; wParam: Longint; var lParam: TComboBoxExItem): Longint; external 'SendMessage{#A}@user32.dll stdcall';
var
GImageList: HIMAGELIST;
GComboBoxEx: HWND;
Icon1: TNewIcon;
//////////////////////////////////////////////////////////
procedure CreateComboBoxExItem(Text, FileName: string);
var
ImageIndex: Integer;
CBItem: TComboBoxExItem;
Icon: TNewIcon;
begin
Icon:= TNewIcon.Create;
ExtractTemporaryFile(FileName);
try
Icon.LoadFromFile(ExpandConstant('{tmp}\'+FileName));
ImageIndex := ImageList_ReplaceIcon(GImageList, -1, Icon.Handle);
finally
Icon.Free;
end;
with CBItem do
begin
mask := CBEIF_TEXT or CBEIF_IMAGE or CBEIF_SELECTEDIMAGE;
iItem := -1;
pszText := Text;
iImage := ImageIndex;
iSelectedImage := ImageIndex;
end;
SendMessageCBEI(GComboBoxEx, CBEM_INSERTITEM, 0, CBItem);
end;
///////////////////////////
procedure CreateComboBoxEx;
begin
{ create comboex } // высота с учетом раскрытого списка
GComboBoxEx := CreateWindowEx(0, WC_COMBOBOXEX, '', WS_VISIBLE or WS_CHILD or CBS_DROPDOWNLIST or CBS_SORT, 0, 0, 320, 320, WizardForm.Handle, 0, HInstance, 0);
{ create imagelist } // высота в итоге свернутого 32 (уситывается ImageList_Create)
GImageList := ImageList_Create(32, 32, ILC_COLOR24{ use ILC_COLOR32 for 32-bit icons }, 0, 0);
{ add items }
CreateComboBoxExItem('Test entry 1', 'Setup1.ico');
CreateComboBoxExItem('Test entry 2', 'Setup2.ico');
{ assign imagelist }
SendMessage(GComboBoxEx, CBEM_SETIMAGELIST, 0, GImageList);
{ set selected item }
SendMessage(GComboBoxEx, CB_SETCURSEL, 0, 0);
end;
////////////////////////////
procedure DestroyComboBoxEx;
begin
if GImageList <> 0 then
DeleteObject(GImageList);
if GComboBoxEx <> 0 then
DestroyWindow(GComboBoxEx);
end;
///////////////////////////
procedure InitializeWizard;
begin
WizardForm.OuterNotebook.Hide;
CreateComboBoxEx;
end;
////////////////////////////
procedure DeinitializeSetup;
begin
DestroyComboBoxEx;
end;
это comboboxex получил фокус - так окрасился.иконка мутная становиться
используй ILC_COLOR32, смотрится лучше.иконка мутная становиться
Зачем? DestroyWindow автоматически уничтожает связанные дочерние или находящиеся в собственности окна, когда она уничтожает окно владельца или родителя. Функция сначала уничтожает дочерние или находящиеся в собственности окна, и затем она уничтожает окно владельца или родителя. Ну или нетImageList_Destroy
[Setup]
AppName=Example
AppVerName=Example 1.0
DefaultDirName={pf}\Example
OutputDir=.
[Files]
Source: Setup1.ico; DestDir: {app}; Check: IsChecked(0);
Source: Setup2.ico; DestDir: {app}; Check: IsChecked(1);
[Code]
#define A = (Defined UNICODE) ? "W" : "A"
const
WM_USER = $0400;
WC_COMBOBOXEX = 'ComboBoxEx32';
WS_CHILD = $40000000;
WS_VISIBLE = $10000000;
WS_TABSTOP = $10000;
CBS_DROPDOWNLIST = $0003;
CBS_SORT = $0100;
ILC_COLOR24 = $0018;
ILC_COLOR32 = $0020;
CBEIF_TEXT = $1;
CBEIF_IMAGE = $2;
CBEIF_SELECTEDIMAGE = $4;
CBEM_INSERTITEM = (WM_USER + {#ifndef UNICODE}1{#else}11{#endif});
CBEM_SETIMAGELIST = (WM_USER + 2);
CB_SETCURSEL = $014E;
WM_COMMAND = $0111;
CBN_SELCHANGE = 1;
CB_GETCURSEL = $0147;
CB_GETCOUNT = $0146;
WM_GETTEXT = $D;
WM_GETTEXTLENGTH = $E;
CB_GETLBTEXT = $0148;
CB_GETLBTEXTLEN = $0149;
//
type
TComboBoxExItem = record
mask: UINT;
iItem: INT_PTR;
pszText: string;
cchTextMax: Integer;
iImage: Integer;
iSelectedImage: Integer;
iOverlay: Integer;
iIndent: Integer;
lParam: Longint;
end;
function CreateWindowEx(dwExStyle: DWORD; lpClassName, lpWindowName: string; dwStyle: DWORD; x, y, nWidth, nHeight: Integer; hWndParent: HWND; hMenu: HMENU; hInstance, lpParam: Longint): HWND; external 'CreateWindowEx{#A}@user32.dll stdcall';
function DestroyWindow(hWnd: HWND): BOOL; external 'DestroyWindow@user32.dll stdcall';
function DeleteObject(hObject: THandle): BOOL; external 'DeleteObject@gdi32.dll stdcall';
function ImageList_Create(cx, cy: Integer; flags: UINT; cInitial, cGrow: Integer): THandle; external 'ImageList_Create@comctl32.dll stdcall';
function ImageList_Destroy(ImageList: HImageList): Bool; external 'ImageList_Destroy@comctl32.dll stdcall';
function ImageList_ReplaceIcon(himl: HIMAGELIST; i: Integer; hIcon: HICON): Integer; external 'ImageList_ReplaceIcon@comctl32.dll stdcall';
function SendMessageCBEI(hWnd: HWND; Msg: UINT; wParam: Longint; var lParam: TComboBoxExItem): Longint; external 'SendMessage{#A}@user32.dll stdcall';
var
GImageList: HIMAGELIST;
GComboBoxEx: HWND;
Icon1: TNewIcon;
function IsChecked(const Index: Integer): Boolean;
begin
Result:= False;
if GComboBoxEx<>0 then
if SendMessage(GComboBoxEx, CB_GETCURSEL, 0, 0)=Index then
Result:= True;
end;
//////////////////////////////////////////////////////////
procedure CreateComboBoxExItem(Text, FileName: string);
var
ImageIndex: Integer;
CBItem: TComboBoxExItem;
Icon: TNewIcon;
begin
Icon:= TNewIcon.Create;
ExtractTemporaryFile(FileName);
try
Icon.LoadFromFile(ExpandConstant('{tmp}\'+FileName));
ImageIndex := ImageList_ReplaceIcon(GImageList, -1, Icon.Handle);
finally
Icon.Free;
end;
with CBItem do
begin
mask := CBEIF_TEXT or CBEIF_IMAGE or CBEIF_SELECTEDIMAGE;
iItem := -1;
pszText := Text;
iImage := ImageIndex;
iSelectedImage := ImageIndex;
end;
SendMessageCBEI(GComboBoxEx, CBEM_INSERTITEM, 0, CBItem);
end;
///////////////////////////
type
LPARAM = Integer;
WPARAM = Integer;
LRESULT = Integer;
TFNWndProc = Integer;
var
OldProc: Longint;
function CallWindowProc(lpPrevWndFunc: TFNWndProc; hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT; external 'CallWindowProc{#A}@user32.dll stdcall';
function SetWindowLong(hWnd: HWND; nIndex: Integer; dwNewLong: Longint): Longint; external 'SetWindowLong{#A}@user32.dll stdcall';
function HiWord(L: DWORD): Word;
begin
Result := L shr 16;
end;
var
Text: String;
nIndex: Integer;
function WindowProc(hWnd: HWND; Msg: UINT; wParam: WPARAM; lParam: LPARAM): LRESULT;
begin
case Msg of WM_COMMAND:
begin
if (lParam=GComboBoxEx) and (HIWORD(wParam) = CBN_SELCHANGE) then
begin
nIndex:= SendMessage(GComboBoxEx, CB_GETCURSEL, 0, 0);
WizardForm.NextButton.Caption:= IntToStr(nIndex); // Выбранная строка
WizardForm.CancelButton.Caption:= IntToStr(SendMessage(GComboBoxEx, CB_GETCOUNT, 0, 0)); // Количество строк
//
Text:= '';
SetLength(Text,SendMessage(GComboBoxEx, CB_GETLBTEXTLEN, nIndex, 0));
SendMessage(GComboBoxEx, CB_GETLBTEXT, nIndex, CastStringToInteger(Text));
if WizardForm.Caption<>Text then
WizardForm.Caption:= Text;
end;
end;
end;
Result := CallWindowProc(OldProc, hWnd, Msg, wParam, lParam);
end;
///////////////////////////
procedure CreateComboBoxEx;
begin
{ create comboex } // высота с учетом раскрытого списка
GComboBoxEx := CreateWindowEx(0, WC_COMBOBOXEX, '', WS_VISIBLE or WS_CHILD or CBS_DROPDOWNLIST or CBS_SORT, ScaleX(20), ScaleX(340), ScaleX(210), ScaleY(320), WizardForm.Handle, 0, HInstance, 0);
{ create imagelist } // высота в итоге свернутого 32 (учитывается ImageList_Create)
GImageList := ImageList_Create(32, 32, ILC_COLOR32{ use ILC_COLOR24 for 24-bit icons }, 0, 0);
{ add items }
CreateComboBoxExItem('Test entry 1', 'Setup1.ico');
CreateComboBoxExItem('Test entry 2', 'Setup2.ico');
{ assign imagelist }
SendMessage(GComboBoxEx, CBEM_SETIMAGELIST, 0, GImageList);
{ set selected item }
SendMessage(GComboBoxEx, CB_SETCURSEL, 0, 0);
if GComboBoxEx <> 0 then
OldProc:= SetWindowLong(WizardForm.Handle, -4, CallbackAddr('WindowProc'));
end;
////////////////////////////
procedure DestroyComboBoxEx;
begin
if GImageList <> 0 then
ImageList_Destroy(GImageList);
if GComboBoxEx <> 0 then
DestroyWindow(GComboBoxEx);
end;
///////////////////////////
procedure InitializeWizard;
begin
// WizardForm.OuterNotebook.Hide;
CreateComboBoxEx;
end;
////////////////////////////
procedure DeinitializeSetup();
begin
SetWindowlong(WizardForm.Handle, -4, OldProc);
DestroyComboBoxEx;
end;
теперь думаю можно.в загашник упёр бы
Узнал как добавить ? Поделишься ?Помогите реализовать такое
Посмотреть вложение 3025
Подскажите пожалуйста, первый раз увидел такую функцию, очень понравилась. но не могу скрыть ее на других страницах инсталла...Lamer.Code, в faq пример есть.