stoer.de // Ollis Internet Heimatseite

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 GOWEBCounter by INLINE

Tipps&Tricks


Wie kann ich verhindern, dass im OwnerDraw-Modus einer TListbox das Fokusrechteck um den markierten Eintrag gezeichnet wird?

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;

Ich habe in einem TDBGrid die Option MultiSelect eingestellt. Wie komme ich zur Laufzeit an die Informationen in den ausgewählten Datensätzen?

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.


Ich suche eine effektive Möglichkeit, die eingestellte Sprache abzufragen....

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.


Ich möchte aus einer *.lnk die Informationen zur eigentlichen Quelle entnehmen.

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;

Wie erzeuge ich Shortcuts in einem Formular ohne Menü?

Es gibt zwei Möglichkeiten:

  1. Du erstellst eine Aktion, die dann den entsprechenden Code ausführt und weist ihr den gewünschten Shortcut zu.
  2. Du fragst den entsprechenden Shortcut im OnKeyDown-Ereignis des Formulars ab.
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;

Wie kann man den Text in einem Editfeld rechtsbündig anzeigen lassen?

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;

Wie kann man das zu einem Dateityp passende Icon in einer Listbox darstellen, ohne dass die Datei existiert?

Der TListView ist mit allem ausgestattet um Icons selbst darzustellen. Man muß nur zwei Probleme lösen:

  1. Wie kommt man an eine TImagelist, die alle Dateiicons enthält?
  2. Wie bekommt man heraus, welches der Images in dieser TImagelist zu einem bestimmten Dateinamen gehört?

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.


Wie kann man ein Menü erstellen, in dem alle MDI-Children aufgelistet werden? Und wenn ich auf ein MenuItem klicke soll das dazugehörige MDI-Child aufgerufen werden.

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