AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Thema durchsuchen
Ansicht
Themen-Optionen

Problem mit IP-Eingabefld

Ein Thema von FriFra · begonnen am 1. Aug 2009 · letzter Beitrag vom 1. Aug 2009
Antwort Antwort
Seite 1 von 2  1 2      
Benutzerbild von FriFra
FriFra

Registriert seit: 19. Apr 2003
1.291 Beiträge
 
Delphi 2005 Professional
 
#1

Problem mit IP-Eingabefld

  Alt 1. Aug 2009, 12:38
Ich hab mir von den Schweizern den Code für: "use the IP Address Control in a Form" geholt und eingebaut.
Das Feld erscheint und hat zu Beginn den Focus, so dass ich hinein schreiben kann. Sobald ich aber das Feld verlasse kann ich nicht mehr den Focus darauf setzen (weder mit Tab, noch mit der Maus).
Delphi-Quellcode:
unit frmEasySettings;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, ComCtrls, ImgList, ToolWin, StdCtrls, Registry, ShellApi, ExtCtrls;

type
  TForm1 = class(TForm)
    PageControl1: TPageControl;
    TabSheet1: TTabSheet;
    TabSheet2: TTabSheet;
    TabSheet3: TTabSheet;
    ToolBar1: TToolBar;
    ToolButton1: TToolButton;
    ToolButton2: TToolButton;
    ToolButton3: TToolButton;
    ImageList1: TImageList;
    GroupBox1: TGroupBox;
    ComboBox1: TComboBox;
    Label1: TLabel;
    ComboBox2: TComboBox;
    IPAddress: TEdit;
    procedure ToolButton1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure SetIPClick(Sender: TObject);
    procedure ClearIPClick(Sender: TObject);
  private
    FIPAddress: Longint;
    HIPAddress: HWND;
    PrevWndProc: TWndMethod;
    procedure NewWindowProc(var Message: TMessage);
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
uses
  CommCtrl;

const
  IP_ADDRESS_ID: Longword = $0100;

procedure TForm1.ToolButton1Click(Sender: TObject);
begin
  close;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  lpInitCtrls: TInitCommonControlsEx;
begin
  lpInitCtrls.dwSize := SizeOf(TInitCommonControlsEx);
  lpInitCtrls.dwICC := ICC_INTERNET_CLASSES;
  if InitCommonControlsEx(lpInitCtrls) then
  begin
    PrevWndProc := WindowProc;
    WindowProc := NewWindowProc;

    HIPAddress := CreateWindowEx(WS_EX_LEFT, WC_IPADDRESS, nil,
      WS_CHILD + WS_VISIBLE + WS_BORDER + WS_TABSTOP,
      IPAddress.Left, IPAddress.Top, IPAddress.Width, IPAddress.Height,
      Tabsheet1.Handle, IP_ADDRESS_ID, HInstance, nil);
    SendMessage(HIPAddress, IPM_SETFOCUS, 0, 0);
  end;
end;

procedure TForm1.NewWindowProc(var Message: TMessage);
var
  nField: longint;
begin
  case Message.Msg of
    WM_NOTIFY:
      begin
        if PNMHDR(Ptr(Message.lParam)).idFrom = IP_ADDRESS_ID then
        begin
          case PNMIPAddress(ptr(Message.lParam)).hdr.code of
            IPN_FIELDCHANGED:
              begin
                if SendMessage(HIPAddress, IPM_ISBLANK, 0, 0) = 0 then
                  SendMessage(HIPAddress, IPM_GETADDRESS, 0,
                    lParam(LPDWORD(@FIPAddress)));
              end;
          end;
        end;
      end;
    WM_COMMAND:
      begin
        if Message.WParamLo = IP_ADDRESS_ID then
          case Message.WParamHi of
            EN_SETFOCUS:
              begin
                nField := SendMessage(HIPAddress, IPM_GETADDRESS, 0,
                  lParam(LPDWORD(@FIPAddress)));
                if nField = 4 then
                  nField := 0;
                SendMessage(HIPAddress, IPM_SETFOCUS, wParam(nField), 0);
              end;
            EN_KILLFOCUS:
              begin
                if SendMessage(HIPAddress, IPM_ISBLANK, 0, 0) = 0 then
                  SendMessage(HIPAddress, IPM_GETADDRESS, 0,
                    lParam(LPDWORD(@FIPAddress)));
              end;
            EN_CHANGE:
              begin
              end;
          end;
      end;
  end;
  if Assigned(PrevWndProc) then
    PrevWndproc(Message);
end;

procedure TForm1.SetIPClick(Sender: TObject);
begin
  FIPAddress := MAKEIPADDRESS(127, 0, 0, 1);
  SendMessage(HIPAddress, IPM_SETADDRESS, 0, lParam(DWORD(FIPAddress)));
end;

procedure TForm1.ClearIPClick(Sender: TObject);
begin
  SendMessage(HIPAddress, IPM_CLEARADDRESS, 0, 0);
end;

end.
Elektronische Bauelemente funktionieren mit Rauch. Kommt der Rauch raus, geht das Bauteil nicht mehr.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.052 Beiträge
 
Delphi 12 Athens
 
#2

Re: Problem mit IP-Eingabefld

  Alt 1. Aug 2009, 12:53
Also das Beispiel von den Schweizern läuft bei mir (D7).



OK, das mit dem Fokusieren via Tab kann nicht funktionieren, da die Tabulatorverwaltung in Delphi unabhängig von den Windows-Controls ist und nur innerhalb der VCL abläuft.

Aber da gibt es Abhilfe:
nimm statt dem TBevel ein TPanel, denn dieses kann in die Tabulatorreinfolge aufgenommen werden.
- im OI beim Panel "IPAddress" das .TabStob auf True setzen
- und dann dieses bei Panel "IPAddress" .OnEnter einfügen
Delphi-Quellcode:
procedure TForm1.IPAddressEnter(Sender: TObject);
begin
  SendMessage(HIPAddress, IPM_SETFOCUS, wParam(0), 0);
end;
Quelle für die Tabulatoränderung: ich ... grad eben ausgedacht
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von FriFra
FriFra

Registriert seit: 19. Apr 2003
1.291 Beiträge
 
Delphi 2005 Professional
 
#3

Re: Problem mit IP-Eingabefld

  Alt 1. Aug 2009, 13:22
Es bleibt dabei, sobald ich das feld verlassen hab kann ich es nicht mehr aktivieren.
Elektronische Bauelemente funktionieren mit Rauch. Kommt der Rauch raus, geht das Bauteil nicht mehr.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.052 Beiträge
 
Delphi 12 Athens
 
#4

Re: Problem mit IP-Eingabefld

  Alt 1. Aug 2009, 13:53
OK, zum Teil liegt es an dem komischen Hook, welcher wohl ab (vermutlich) Delphi2006 oder so, nicht mehr richtig mitspielt ... hab den mal in seine Messages zerlegt.

Man müßte nur mal das OnClick überarbeiten ... wenn man da die Mausposition beachtet, dann könnte man versuchen das Feld unter dem Klick zu aktivieren und nicht immer nur das Erste.

benötigt:
TPanel: IPAddress
TButton: SetIP und ClearIP

Panel(IPAddress).TabStop = True
Panel(IPAddress).OnClick = IPAddressEnter
Panel(IPAddress).OnEnter = IPAddressEnter
Delphi-Quellcode:
unit Unit1;

interface

uses
  Windows, Messages, Classes, Forms, Controls, StdCtrls, ExtCtrls;

type
  TForm1 = class(TForm)
    IPAddress: TPanel;
    SetIP: TButton;
    ClearIP: TButton;
    procedure FormCreate(Sender: TObject);
    procedure IPAddressEnter(Sender: TObject);
    procedure SetIPClick(Sender: TObject);
    procedure ClearIPClick(Sender: TObject);
  private
    FIPAddress: Longint;
    HIPAddress: HWND;
    procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
    procedure WMCommand(var Message: TWMCommand); message WM_COMMAND;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

uses
  CommCtrl;

const
  IP_ADDRESS_ID: Longword = $0100;

procedure TForm1.FormCreate(Sender: TObject);
var
  lpInitCtrls: TInitCommonControlsEx;
begin
  lpInitCtrls.dwSize := SizeOf(TInitCommonControlsEx);
  lpInitCtrls.dwICC := ICC_INTERNET_CLASSES;
  if InitCommonControlsEx(lpInitCtrls) then
  begin
    HIPAddress := CreateWindowEx(WS_EX_LEFT, WC_IPADDRESS, nil,
      WS_CHILD or WS_VISIBLE or WS_BORDER or WS_TABSTOP,
      IPAddress.Left, IPAddress.Top, IPAddress.Width, IPAddress.Height,
      Handle, IP_ADDRESS_ID, HInstance, nil);
    SendMessage(HIPAddress, IPM_SETFOCUS, 0, 0);
  end;
end;

procedure TForm1.IPAddressEnter(Sender: TObject);
begin
  SendMessage(HIPAddress, IPM_SETFOCUS, wParam(0), 0);
end;

procedure TForm1.SetIPClick(Sender: TObject);
begin
  FIPAddress := MAKEIPADDRESS(127, 0, 0, 1);
  SendMessage(HIPAddress, IPM_SETADDRESS, 0, lParam(DWORD(FIPAddress)));
end;

procedure TForm1.ClearIPClick(Sender: TObject);
begin
  SendMessage(HIPAddress, IPM_CLEARADDRESS, 0, 0);
end;

procedure TForm1.WMNotify(var Message: TWMNotify);
var
  nField: longint;
begin
  if Message.NMHdr.idFrom = IP_ADDRESS_ID then
  begin
    case Message.NMHdr.code of
      IPN_FIELDCHANGED:
        begin
          if SendMessage(HIPAddress, IPM_ISBLANK, 0, 0) = 0 then
            SendMessage(HIPAddress, IPM_GETADDRESS, 0, lParam(LPDWORD(@FIPAddress)));
        end;
      else
        inherited;
    end;
  end
  else
    inherited;
end;

procedure TForm1.WMCommand(var Message: TWMCommand);
var
  nField: longint;
begin
  if Message.ItemID = IP_ADDRESS_ID then
  begin
    case Message.NotifyCode of
      EN_SETFOCUS:
        begin
          nField := SendMessage(HIPAddress, IPM_GETADDRESS, 0,
            lParam(LPDWORD(@FIPAddress)));
          if nField = 4 then nField := 0;
          SendMessage(HIPAddress, IPM_SETFOCUS, wParam(nField), 0);
        end;
      EN_KILLFOCUS:
        begin
          if SendMessage(HIPAddress, IPM_ISBLANK, 0, 0) = 0 then
            SendMessage(HIPAddress, IPM_GETADDRESS, 0, lParam(LPDWORD(@FIPAddress)));
        end;
      EN_CHANGE:
        begin
        end;
      else
        inherited;
    end;
  end
  else
    inherited;
end;

end.
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von FriFra
FriFra

Registriert seit: 19. Apr 2003
1.291 Beiträge
 
Delphi 2005 Professional
 
#5

Re: Problem mit IP-Eingabefld

  Alt 1. Aug 2009, 14:02
Also ich verwende dafür gerade Delphi7... Es funktioniert garnicht...

OK, jetzt, wo ich IPAddressEnter auch auf Onclick liegen hab, aktiviert man da sFeld auch mit nem Klick... AAABER es ist unmöglih Blöcke < 3 Zeichen einzugeben, da der Pfeil nach rechts nicht funktioniert und das Feld dadurch den focus verliert... ich kann also nur 222.222.222.222 eintipen, weil der cursor nach dem driten Zeichen in den nächsten Block springt, aber 127.0.0.1 geht garnicht, weil ich nach der ersten 0 nicht weiter komme.
Elektronische Bauelemente funktionieren mit Rauch. Kommt der Rauch raus, geht das Bauteil nicht mehr.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.052 Beiträge
 
Delphi 12 Athens
 
#6

Re: Problem mit IP-Eingabefld

  Alt 1. Aug 2009, 14:15
Was die Pfeiltasten angeht, wenn du die auch haben willst, dann mußt du auch noch die Tastensteuerung ändern, da standardmäßig die Pfeile zum Controlwechsel genutzt werden.

Vergiß nicht, daß du hier ein Windows-Control direkt ohne VCL einbauen willst und demnach mußt du dich auch um alles selber kümmern
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von FriFra
FriFra

Registriert seit: 19. Apr 2003
1.291 Beiträge
 
Delphi 2005 Professional
 
#7

Re: Problem mit IP-Eingabefld

  Alt 1. Aug 2009, 14:20
Ok, aber dann ist der Code der Schweizer völlig wertlos, weil er so eben unbrauchbar ist. Was nützt einem ein schickes Feld, wenn man dann nichts eintippen kann? ... dann hätte mans ja gleich auf den canvas zeichnen können

Trotzdem Danke, für die Tips.

P.S.: Ich nehm jetzt ein normales Textfeld, weil ich einfach keine Lust hab hier noch mehr Zeit damit zu verbrennen dieses Control in einer brauchbaren Form in meinem VCL-Projekt zu verwenden. Ich will meine Zeit in die Applikations-Logik stecken und nicht ins GUI. Fremdkomponenten sind übrigens keine Option.
Elektronische Bauelemente funktionieren mit Rauch. Kommt der Rauch raus, geht das Bauteil nicht mehr.
  Mit Zitat antworten Zitat
Benutzerbild von himitsu
himitsu

Registriert seit: 11. Okt 2003
Ort: Elbflorenz
44.052 Beiträge
 
Delphi 12 Athens
 
#8

Re: Problem mit IP-Eingabefld

  Alt 1. Aug 2009, 14:28
erster Versuch:
Delphi-Quellcode:
uses CommCtrl;

type TIPEdit = class(TWinControl)
    procedure CreateParams(var Params: TCreateParams); override;
  end;

procedure TIPEdit.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  CreateSubClass(Params, WC_IPADDRESS);
  with Params do
  begin
    if NewStyleControls and Ctl3D then
    begin
      Style := Style and not WS_BORDER;
      ExStyle := ExStyle or WS_EX_CLIENTEDGE;
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var
  E: TIPEdit;
begin
  E := TIPEdit.Create(Self);
  E.Parent := Self;
  E.Left := 8;
  E.Top := 8;
  E.Width := 100;
  E.Height := 21;
end;
fehlt noch ein schicker Constructor und ein Property+Getter/Setter und Clear für die IP
(den Code hab ich mir vom TEdit gemopst)
Neuste Erkenntnis:
Seit Pos einen dritten Parameter hat,
wird PoSex im Delphi viel seltener praktiziert.
  Mit Zitat antworten Zitat
Benutzerbild von Matze
Matze
(Co-Admin)

Registriert seit: 7. Jul 2003
Ort: Schwabenländle
14.929 Beiträge
 
Turbo Delphi für Win32
 
#9

Re: Problem mit IP-Eingabefld

  Alt 1. Aug 2009, 14:46
Ich würde ein normales TEdit nutzen. Wenn der Anwender eine IP-Adresse eingeben muss, dann weiß er in der Regel auch, wie eine solche aussieht bzw. er sollte das wissen. Die Gültigkeit kannst du im OnChange o.ä. dann überprüfen. Ein weiterer Vorteil ist auch, dass IPv6-Adressen ebenfalls unterstützt werden.
Alles andere sind irgendwelche Frickellösungen mit manuell programmierten Eingabebeschränkungen und daher auch potentielle Fehlerquellen.
  Mit Zitat antworten Zitat
Benutzerbild von sx2008
sx2008

Registriert seit: 16. Feb 2008
Ort: Baden-Württemberg
2.332 Beiträge
 
Delphi 2007 Professional
 
#10

Re: Problem mit IP-Eingabefld

  Alt 1. Aug 2009, 15:52
Ich würde empfehlen, das IP Address Control überhaupt nicht zu verwenden.
Auf den ersten Blick mag es logisch sein, eine streng formatierte Eingabe zu präsentieren.
Aber wenn man selbst das Control benützt, dann nerven die Einschränkungen doch gewaltig.
* Copy & Paste funktioniert nicht.
Man steckt immer in der ersten Zahl vor dem ersten Punkt fest und muss dann die IP-Adresse ABTIPPEN.
Also ich hasse es wenn ich eine IP abtippen muss.
* keine Möglichkeit einen Rechnernamen einzugeben
ich möchte bitteschön einen Rechnernamen eingeben können; das Programm soll die Namensauflösung durchführen
und die Eingabe durch die IP Adresse ersetzen. Soviel Komfort muss sein.
* Control reagiert nicht auf den Punkt
ich bin immer etwas irritiert, wenn ich die erste Zahl eingegeben habe und dann den Punkt eingebe:
nichts passiert
man muss Pfeil nach rechts drücken um zur 2. Zahl zu kommen.
Das Control sollte sich dem Benutzer anpassen nicht umgekehrt.

Alternative Lösung:
* ein normales TEdit verwenden
* das Editfeld zeigt folgenden Inhalt [ . . . ] solange es nicht den Fokus hat
und noch keine Eingabe getätigt wurde. Damit wird dem Benutzer gezeigt: "hier eine IP eingeben"
* erhält das Edit den Fokus, wird der Inhalt [ . . . ] gelöscht (Event OnEnter)
* wird das Feld verlassen (Event OnExit) wird geprüft, ob es sich um eine vollständige und korrekte IP handelt.
Sollte das Feld 3 Punkte und nur Ziffern enthalten, aber keine gültige IP sein - Exception werfen
Enthält das Feld genau 8 Hexzeichen? Umwandeln in dezimale IP.
Ansonsten wird versucht eine Namensauflösung durchzuführen.
Falls Namensauflösung erfolgreich: IP in Editfeld kopieren
Falls Namensauflösung nicht erfolgreich: Exception werfen (Feld nicht verlassen)


Diese Lösung verwendet keine Low-Lewel-Funktionen und ist auf jeder Windowsversion und sogar anderen Betriebssystemen lauffähig.

@Matze: Hey, das wollte ich auch schreiben, hatte es nur noch nicht abgeschickt
fork me on Github
  Mit Zitat antworten Zitat
Antwort Antwort
Seite 1 von 2  1 2      


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 · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:17 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz