AGB  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein FreePascal Nach BringToFront wieder über Tasten navigieren?

Nach BringToFront wieder über Tasten navigieren?

Ein Thema von Partikelecho · begonnen am 13. Apr 2012 · letzter Beitrag vom 18. Apr 2012
Antwort Antwort
Partikelecho

Registriert seit: 2. Dez 2011
14 Beiträge
 
Delphi 6 Enterprise
 
#1

Nach BringToFront wieder über Tasten navigieren?

  Alt 13. Apr 2012, 11:32
Hallo liebe DPler,
ich schreibe gerade eine kleine Anwendung für einen Freund in Lazarus (0.9.30.4). Im Prinzip werden nur ein paar Werte in eine Liste gepackt (per Button) und abhängig von den bisherigen Werten verschiedene Möglichkeiten in Betracht gezogen. Das tut auch nichts zur Sache.

Wichtig bei dieser Anwendung wäre allerdings, dass es sich nach dem "Deaktivieren" durch Klick auf ein anderes Fenster wieder in den Vordergrund bringt und auch wieder per Tastatur steuerbar ist.

Folgende Tastatureingaben werden über das KeyDown-Event des Hauptformulars abgefangen und rufen die OnClick-Prozeduren von 4 Buttons auf.
Delphi-Quellcode:
procedure Tfrm_main.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
  37: // Aktion für VK_LEFT;
  40: // Aktion für VK_DOWN;
  39: // Aktion für VK_RIGHT;
  38: // Aktion für VK_UP;
  end;
end;
Das Formular ist momentan aus BorderStyle bsDialog und FormStyle fsNormal eingestellt und wird wie folgt im OnShow-Event geTOPMOSTet:
Delphi-Quellcode:
procedure Tfrm_main.FormShow(Sender: TObject);
begin
  SetWindowPos(Handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE or SWP_NOMOVE or SWP_NOSIZE);
end;
Da das aber allein nicht funktioniert hat, habe bringe ich das Fenster mit Hilfe eines Timers immer wieder in den Vordergrund. Das ist die Stelle die mir ganz und garnicht gefällt und sicher nicht zum guten Stil gehört.
Im OnTimer-Event wird also immer wieder BringToFront ausgelöst.
Delphi-Quellcode:
procedure Tfrm_main.Timer1Timer(Sender: TObject);
begin
  if GetForeGroundWindow <> Handle then
  begin
    frm_main.BringToFront;
  end;
end;
Nochmal das Ziel: Dieses kleine Formular soll auch nach Aktion in einem anderen Fenster (ist soweit ich weiß kein Spiel und auch nicht maximiert/Vollbild, ...) wieder durch die Pfeiltasten navigierbar sein.
Soweit ich weiß, lassen sich Anwendungen nicht mehr den Focus stehlen. Damit dürfte es dann nicht gehen.
  Mit Zitat antworten Zitat
shmia

Registriert seit: 2. Mär 2004
5.508 Beiträge
 
Delphi 5 Professional
 
#2

AW: Nach BringToFront wieder über Tasten navigieren?

  Alt 13. Apr 2012, 13:29
Ganz so klar ist mir das nicht geworden, aber ich würde das Window-Handle
dieser 2. Anwendung zwischenspeichern und BringToFront()
nur auslösen, wenn diese 2. Anwendung den Focus hat:
Delphi-Quellcode:
Tfrm_main = class(TForm)
private
  FExtWinHandle : THandle;
....

procedure Tfrm_main.Timer1Timer(Sender: TObject);
begin
  if GetForeGroundWindow <> Handle then
  begin
    if FExtWinHandle = 0 then
    begin
      FExtWinHandle := GetForeGroundWindow;
    end;

    if FExtWinHandle = GetForeGroundWindow then
      BringToFront;
  end;
end;

procedure Tfrm_main.FormOnActivate(Sender: TObject);
begin
  FExtWinHandle := 0;
end;
Damit kann der Benutzer zwischendurch auch eine andere Anwendung (z.B. Explorer)
benützen ohne das deine Anwendung ständig hochpoppt.
Andreas
  Mit Zitat antworten Zitat
Benutzerbild von Dalai
Dalai

Registriert seit: 9. Apr 2006
477 Beiträge
 
Delphi 5 Professional
 
#3

AW: Nach BringToFront wieder über Tasten navigieren?

  Alt 13. Apr 2012, 18:44
Wichtig bei dieser Anwendung wäre allerdings, dass es sich nach dem "Deaktivieren" durch Klick auf ein anderes Fenster wieder in den Vordergrund bringt und auch wieder per Tastatur steuerbar ist.
Was für ein anderes Fenster? Ein anderes Formular derselben Anwendung oder ein fremdes Programm?

MfG Dalai
  Mit Zitat antworten Zitat
Partikelecho

Registriert seit: 2. Dez 2011
14 Beiträge
 
Delphi 6 Enterprise
 
#4

AW: Nach BringToFront wieder über Tasten navigieren?

  Alt 14. Apr 2012, 16:58
@Dalai:
Ein fremdes Programm bzw. das Hauptfenster von diesem.

@shmia:
Das macht Sinn, guter Vorschlag. Es geht auch "nur" darum in der anderen Anwendung ein paar Klicks zu machen und anschließend mit den Pfeiltasten in meiner kleinen Anwendung ein paar Buttons auszulösen. Praktisch wäre es z.B. auch, wenn die andere Anwendung durch Auslösen einer Taste wieder zu meiner Anwendung springt - dann hätte man selbst die Kontrolle, wann man wieder was in der kleinen App machen möchte.

Aber erstmal eins nach dem andern. Ich habe jetzt im Delphi-Treff eine Funktion gefunden, mit der ich nach Fenstername oder einem Teil davon ODER nach dem Klassennamen eines Fensters suchen kann. Ein Editor hat z.B. im Titel immer " - Editor" stehen, so könnte ich dieses Fenster dann finden. Vorausgesetzt natürlich, es gibt nicht noch ein weiteres.

Delphi-Treff: Handle auf ein Fenster einer anderen Anwendung bekommen:
http://www.delphi-treff.de/tipps/sys...dung-bekommen/

Ich hab jetzt ne Weile gebastelt und habs geschafft die Codes vom Delphi-Treff so gut es geht lazarus-konform bzw. 64-bit konform zu machen.

Delphi-Quellcode:
unit MainForm;

{$mode objfpc}{$H+}

interface

uses
  Windows, Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs,
  StdCtrls, ExtCtrls;

type
  PFindWindowStruct = ^TFindWindowStruct;
  TFindWindowStruct = record
    Caption: string;
    ClassName: String;
    WindowHandle: THandle;
  end;
type
  Tfrm_main = class(TForm)
    // Buttons, Labels, ...
    Timer1: TTimer;
    procedure FormActivate(Sender: TObject);
    procedure FormKeyDown(Sender: TObject; var Key: Word; Shift: TShiftState);
    procedure FormShow(Sender: TObject);
    procedure Timer1Timer(Sender: TObject);
    // restliche Prozeduren
  private
    FExtWinHandle: THandle;
    { private declarations }
  public
    { public declarations }
  end;

var
  frm_main: Tfrm_main;
  function FindAWindow(WinCaption: String; WinClassName: String): THandle;
  function EnumWindowsProc(hWindow: hWnd; lParam: PtrInt): Bool; stdcall;

implementation

{$R *.lfm}

{ Tfrm_main }

//------------------------------------------------------------------------------

procedure Tfrm_main.FormKeyDown(Sender: TObject; var Key: Word;
  Shift: TShiftState);
begin
  case Key of
  37: // Aktion für VK_LEFT;
  40: // Aktion für VK_DOWN;
  39: // Aktion für VK_RIGHT;
  38: // Aktion für VK_UP;;
  end;
end;

//------------------------------------------------------------------------------

procedure Tfrm_main.FormActivate(Sender: TObject);
begin
  FExtWinHandle := 0;
end;

//------------------------------------------------------------------------------

function EnumWindowsProc(hWindow: hWnd; lParam: PtrInt): Bool; Stdcall;
var
  lpBuffer: PChar;
  WindowCaptionFound: Boolean;
  ClassNameFound: Boolean;
begin
  GetMem(lpBuffer, 255);
  Result := True;
  WindowCaptionFound := False;
  ClassNameFound := False;
  try
    if GetWindowText(hWindow, lpBuffer,255)>0 then
      if Pos(PFindWindowStruct(lParam)^.Caption, StrPas(lpBuffer))>0 then
        WindowCaptionFound := True;
    if PFindWindowStruct(lParam)^.ClassName='then
      ClassNameFound := True
    else if GetClassName(hWindow, lpBuffer, 255)>0 then
      if Pos(PFindWindowStruct(lParam)^.ClassName, StrPas(lpBuffer))>0 then
        ClassNameFound := True;
    if (WindowCaptionFound and ClassNameFound) then
    begin
      PFindWindowStruct(lParam)^.WindowHandle := hWindow;
      Result := False;
    end;
  finally
    FreeMem(lpBuffer, SizeOf(lpBuffer^));
  end;
end;

//------------------------------------------------------------------------------

function FindAWindow(WinCaption: String; WinClassName: String): THandle;
var
  WindowInfo: TFindWindowStruct;
begin
  with WindowInfo do
  begin
    Caption := WinCaption;
    ClassName := WinClassName;
    WindowHandle := 0;
    EnumWindows(@EnumWindowsProc, PtrInt(@WindowInfo));
    Result := WindowHandle;
  end;
end;

//------------------------------------------------------------------------------

procedure Tfrm_main.Timer1Timer(Sender: TObject);
var
  FMyHandle: THandle;
begin
  FMyHandle := FindAWindow('- Editor', '');
  if GetForeGroundWindow <> Handle then
  begin
    if FExtWinHandle = 0 then
      FExtWinHandle := GetForeGroundWindow;
    if FExtWinHandle = FMyHandle then
    begin
      BringToFront;
      {if frm_main.WindowState = wsMinimized then
        frm_main.WindowState := wsNormal;
      if not frm_main.Active then
        SetActiveWindow(Application.MainForm.Handle);
      if not frm_main.Focused then
        Application.MainForm.SetFocus;
      SetForegroundWindow(Application.MainForm.Handle);}

    end;
  end;
end;
- Der Timer überprüft im Moment dauerhaft, ob ein Fenster mit dem Namen oder Teilnamen " - Editor" vorhanden ist und führt dann BringToFront aus - Wie wird das Fenster nun so nach vorn gehoben, dass ich es wieder mit den Maustasten bedienen kann?
- Neben BringToFront habe ich auch SetForegroundWindow(Application.MainForm.Handle) bzw. SetActiveWindow(Application.MainForm.Handle), SetFocus, Activate, etc. versucht. Das Fenster kommt nicht vor.

weitere Infos:
- Das Fenster wird nicht minimiert (Stellt euch 2 Notepads vor, die sich teilweise überlappen und man dann eins anklickt -> das andere liegt dann dahinter)
- Das Fenster hat BorderStyle bsDialog und FormStyle fsNormal
- die ganzen im Vordergrund bleiben Geschichten hab ich raus genommen

Geändert von Partikelecho (15. Apr 2012 um 15:04 Uhr)
  Mit Zitat antworten Zitat
Partikelecho

Registriert seit: 2. Dez 2011
14 Beiträge
 
Delphi 6 Enterprise
 
#5
  Alt 18. Apr 2012, 17:47
(push, kann gelöscht werden)

Geändert von Partikelecho (18. Apr 2012 um 20:34 Uhr)
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu
Online

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
27.746 Beiträge
 
Delphi XE3 Professional
 
#6

AW: Nach BringToFront wieder über Tasten navigieren?

  Alt 18. Apr 2012, 17:58
Bietet Lazarus nicht auch einen FormStyle ala StayOnTop?
Tut mir Leid das sagen zu müssen, aber sowas wie mit diesem Timer ist doch totaler Schrott unschön.

Und ja, wenn der Eingabefokus nicht bei deiner Form liegt, dann bekommt sie natürlich auch keine Eingabebefehle (Tastenereignisse).

MSDN-Library durchsuchenGetAsyncKeyState



PS:
Zitat:
Delphi-Quellcode:
case Key of
  37: // Aktion für VK_LEFT;
  40: // Aktion für VK_DOWN;
  39: // Aktion für VK_RIGHT;
  38: // Aktion für VK_UP;
end;
Mit gutem Code, kann man sich nutzlose Kommentare ersparen.
Delphi-Quellcode:
case Key of
  VK_LEFT: ;
  VK_DOWN: ;
  VK_RIGHT: ;
  VK_UP: ;
end;
Garbage Collector ... Delphianer erzeugen keinen Müll, also brauchen sie auch keinen Müllsucher.
Delphi-Tage 2005-2014

Geändert von himitsu (18. Apr 2012 um 18:00 Uhr)
  Mit Zitat antworten Zitat
Partikelecho

Registriert seit: 2. Dez 2011
14 Beiträge
 
Delphi 6 Enterprise
 
#7

AW: Nach BringToFront wieder über Tasten navigieren?

  Alt 18. Apr 2012, 20:32
Hallo himitsu,

Zunächst mal zum KeyDown-Event. Die Konstanten wurden nicht angenommen, darum habe ich kurzerhand die numerischen Werte verwendet. Damit wollte ich micht nicht lange aufhalten.
Die Kommentare sind bei mir auch nicht im Code, weil dort entsprechende Prozeduraufrufe stehen. Das war nur als Hilfe für euch, damit ihr nicht erst schauen müsst wofür jetzt welche Zahl steht.

Von diesen "Fenster soll immer oben bleiben" Geschichte hab ich mich schon so halb verabschiedet. Es langt, wenn ich das Fenster wieder Aktivieren kann bzw. ihm ordnungsgemäß den Fokus übergeben kann.

Die Sache mit dem Timer war nur ne Quick and Dirty Lösung, um zu testen, welche Möglichkeiten funktionieren, mein Fenster wieder zu reaktivieren. Bisher war mein "Radius" beim Programmieren in Delphi lediglich auf die eigene Anwendung und vielleicht ein paar externe Dateien begrenzt. Mit der Interaktion zu anderen Programmen habe ich wenig bis gar keine Erfahrung. Deshalb ist mir bisher auch noch nichts anderes eingefallen, was ich nutzen könnte, diese lästige Timer-Gesichte zu beseitigen.

Falls sich da am Wochenende - wo ich hierfür wieder bisschen Luft hätte - nicht noch was auftut beschäftige ich mal mit GetAsyncKeyState. Danke schon mal für den Tipp
  Mit Zitat antworten Zitat
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 00:55 Uhr.
Powered by vBulletin® Copyright ©2000 - 2014, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2014 by Daniel R. Wolf