Navigator:
Startseite |
Links
Software: Outpod |
Screensaver
Der Stör: Wissenswertes |
Fisch des Jahres |
Links
Palm: Mein m505 |
Links /
Speichererweiterung
Richtig nutzen |
PowerRun |
MSMount
Delphi:
Komponenten
Actions |
URL-Label / Resourcen
Links |
Tipps&Tricks |
Kontakt
Das Problem liegt in TCustomListBox.CNDrawItem.
Diese Methode fängt die CN_DRAWITEM messages ab und zeichnet einen Eintrag, wenn einer der OwnerDraw-Styles ausgewählt ist.
Man muss eine eigene Komponente von TListbox ableiten und diese Methode überschreiben. Da sie in TCustomListBox private ist, bleibt nichts anderes übrig, als den Quelltext der Methode zu kopieren und komplett in die neue Komponente zu übernehmen. In dem kopierten Quelltext müssen alle Verweise auf private Felder in Verweise auf Eigenschaften geändert und die Zeile
if odFocused in State then DrawFocusRect(hDC, rcItem);
auskommentiert werden.
Die Komponente könnte also etwa so aussehen:
interface
type
TMyListbox = class(TListbox)
private
procedure CNDrawItem(var Message: TWMDrawItem); message
CN_DRAWITEM;
end;
implementation
procedure TMyListBox.CNDrawItem(var Message: TWMDrawItem);
var
State: TOwnerDrawState;
begin
with Message.DrawItemStruct^ do
begin
State := TOwnerDrawState(LongRec(itemState).Lo);
Canvas.Handle := hDC;
Canvas.Font := Font;
Canvas.Brush := Brush;
if (Integer(itemID) >= 0) and (odSelected in State) then
begin
Canvas.Brush.Color := clHighlight;
Canvas.Font.Color := clHighlightText
end;
if Integer(itemID) >= 0 then
DrawItem(itemID, rcItem, State) else
Canvas.FillRect(rcItem);
// if odFocused in State then DrawFocusRect(hDC, rcItem);
Canvas.Handle := 0;
end;
end;
|
Delphi bietet im TDBGrid keine direkte Möglichkeit an die ausgewählten Datensätze im dahinterliegenden TDataset zu kommen. Deshalb muss man den Umweg über die Funktion GotoBookmark gehen.
procedure TForm1.Button1Click(Sender: TObject);
var
I : Integer;
begin
if DBGrid1.SelectedRows.Count > 0 then
with DBGrid1.DataSource.DataSet do
for I := 0 to DBGrid1.SelectedRows.Count - 1 do
begin
GotoBookmark(Pointer(DBGrid1.SelectedRows.Items[I]));
with DBGrid1.DataSource.DataSet do
ListBox1.Items.Add(FieldByName('CustNo').AsString);
end;
end; |
Für weitere Informationen siehe die Technical Info TI2976 'TDBGrid and Multi-Selecting Records' auf der Borland Website.
SysLocale.PriLangID und SysLocale.SubLangID enthalten die Primary Language ID und die Sub Language ID. Die Bedeutung der zurückgelieferten Werte wird in der Hilfe zur Win32 API unter "Language Identifiers and Locales" erklärt.
Man muss die Units ComObj, ActiveX und ShlObj einbinden. Dann sollte die Methode zum Abfragen der Informationen etwa so aussehen.
procedure TForm1.Button1Click(Sender: TObject);
var
IU : IUnknown;
SL : IShellLink;
PF : IPersistFile;
FindDate : TWin32FindData;
TargetFile : array[0..MAX_PATH] of char;
LinkFile : WideString;
begin
LinkFile:='c:\test.lnk';
{ Herstellen des IShellLink und IPersistFile zum Zugriff auf
die .LNK Datei. }
IU := CreateComObject(CLSID_ShellLink);
SL := IU as IShellLink;
PF := SL as IPersistFile;
{ .LNK Datei in IPersistFile Objekt laden. }
PF.Load(PWideChar(LinkFile), STGM_READ);
{ Den Link durch Aufruf der Resolve-Methode auflösen }
SL.Resolve(0, SLR_ANY_MATCH or SLR_NO_UI);
{ Jetzt kommt man an die Infos }
SL.GetPath(TargetFile, MAX_PATH, FindDate, SLGP_UNCPRIORITY);
{ Zieldatei ausgeben }
ShowMessage(TargetFile);
end;
|
Es gibt zwei Möglichkeiten:
procedure TForm1.FormKeyDown(Sender: TObject; var Key: Word;
Shift: TShiftState);
begin
if (Key = Ord('B')) and (Shift = [ssCtrl, ssAlt]) then
ShowMessage('Shortcut gedrückt');
end;
|
Am einfachsten ist die Verwendung eines TMemo mit der gleichen Höhe wie ein Editfeld. WantReturns und WordWrap müssen auf False gesetzt weden. Im OnKeyPress Ereignis wird die Tastenkombination Strg+Enter abgefangen.
procedure TForm1.Memo1KeyPress(Sender: TObject; var Key: Char); begin If Key = #10 Then Key := #0; end; |
Der TListView ist mit allem ausgestattet um Icons selbst darzustellen. Man muß nur zwei Probleme lösen:
Für beide Probleme verwendest man die Funktion SHGetFileInfo. Sie ist in Win32.hlp dokumentiert.
Lösung zu Punkt 1:
Als erstes musst man eine Imagelist mit den Dateiicons erzeugen. Das passiert am besten in einer Init-Methode, die beim FormCreate aufgerufen wird.
Viewer ist eine TListView-Komponente.
procedure TFrmMain.Init;
var
SysIL : HImageList;
SFI : TSHFileInfo;
begin
{ Create image list component }
Viewer.SmallImages := TImageList.Create(Self);
{ Get the List of small ShellIcons }
SysIL := SHGetFileInfo('', 0, SFI, SizeOf(SFI),
SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
if SysIL <> 0 then
begin
{ Assign system image liste to viewer }
Viewer.SmallImages.Handle := SysIL;
{ Prevent destruction of system images }
Viewer.SmallImages.ShareImages := True;
end;
end;
|
Lösung zu Punkt 2:
Wenn eine Datei im Opendialog ausgewählt wird, sollte man eine Methode aufrufen, um diesen Dateinamen und das Icon im ListView hinzuzufügen. Bei mir heißt sie AddFileToList
procedure TFrmMain.AddFileToList(AFileName : String);
var
NewItem: TListItem;
i: integer;
begin
Viewer.Items.BeginUpdate;
try
NewItem := Viewer.Items.Add;
with NewItem do
begin
Caption := ExtractFileName(AFileName);
{ Jede Datei bekommt das zum Dateinamen passende Icon. }
ImageIndex := GetIconIndex(AFileName, FILE_ATTRIBUTE_NORMAL);
{ Und den Pfadnamen }
SubItems.Add(ExtractFilePath(AFileName));
end; // with
finally
Viewer.Items.EndUpdate;
end;
end;
|
Die entscheidende Frage hier ist: "Welches Icon gehört zu welcher Dateierweiterung". Dazu habe ich die GetIconIndex-Methode, die den passenden Index innerhalb der in Init erzeugten ImageList liefert. Sie benutzt ebenfalls SHGetFileInfo
function TFrmMain.GetIconIndex(const AFileName: string;
Attrs: DWORD): integer;
var
SFI : TSHFileInfo;
begin
SHGetFileInfo(PChar(AFileName), Attrs, SFI, SizeOf(TShFileInfo),
SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES);
Result := SFI.iIcon;
end;
|
SHGFI_USEFILEATTRIBUTES in Kombination mit FILE_ATTRIBUTES_NORMAL bringt Windows dazu zu glauben, dass die Datei in Wirklichkeit existiert.
Das Verfahren, das ich hier verwende, ist in der Microsoft Knowledge Base im Artikel Q179167 HOWTO: Retrieve an Icon for a File Class Without a File genau beschrieben.
Man muß dem MDI-Hauptformular mitteilen an welchen Menüpunkt die Liste der MDI-Childs angehängt wird. Das geht durch setzen der Eigenschaft WindowMenu.
Achtung! Im entsprechenden Menüeintrag muss es mindestens einen Untermenüpunkt geben.
Letzte Änderung: 19. Juli 2002. Alle Rechte vorbehalten, Oliver Stör