![]() |
Problem mit IP-Eingabefld
Ich hab mir von den Schweizern den Code für: "
![]() 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. |
Re: Problem mit IP-Eingabefld
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:
Quelle für die Tabulatoränderung:
procedure TForm1.IPAddressEnter(Sender: TObject);
begin SendMessage(HIPAddress, IPM_SETFOCUS, wParam(0), 0); end; ![]() |
Re: Problem mit IP-Eingabefld
Es bleibt dabei, sobald ich das feld verlassen hab kann ich es nicht mehr aktivieren. :roll:
|
Re: Problem mit IP-Eingabefld
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. |
Re: Problem mit IP-Eingabefld
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. |
Re: Problem mit IP-Eingabefld
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 :zwinker: |
Re: Problem mit IP-Eingabefld
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 :lol:
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. |
Re: Problem mit IP-Eingabefld
erster Versuch:
Delphi-Quellcode:
fehlt noch ein schicker Constructor und ein Property+Getter/Setter und Clear für die IP
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; (den Code hab ich mir vom TEdit gemopst) |
Re: Problem mit IP-Eingabefld
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
![]() Alles andere sind irgendwelche Frickellösungen mit manuell programmierten Eingabebeschränkungen und daher auch potentielle Fehlerquellen. ;) |
Re: Problem mit IP-Eingabefld
Ich würde empfehlen, das IP Address Control überhaupt nicht zu verwenden. :warn:
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 :zwinker: |
Alle Zeitangaben in WEZ +1. Es ist jetzt 13:43 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz