Benutzer mit den meisten Antworten
Textbox Zusatzinfos in die Textbox zeichnen

Frage
-
Hi,
Ich hab lange versucht, mittels Überschreibung von OnPaint und setzten von ControlStyles.UserPaint in meiner TextBox-Ableitung etwas in die TextBox zu zeichnen. Aber das scheint wohl so nicht angedacht zu sein.
Schon alleine durch Setzten von ControlStyles.UserPaint auf true ohne irgendwelche anderen Einflußnamen (Kein Zeichnen keine Events, sozusagen nackte Ableitung) wird die TextBox unbenutzbar. Enthaltene Texte werden erst angezeigt wenn man draufklickt und nur solange man den Mauszeiger über der TextBox hält.
Hab ich mich nach was anderem umgeschaut und bis letztendlich beim Überschreiben von WndProc und einem eher ungünstigen Hack hängengeblieben.
protected override void WndProc(ref Message m) { // Turn off context menu if (m.Msg != (int)WindowsMessages.WM_CONTEXTMENU) base.WndProc(ref m); // Windows Paint message if (m.Msg == (int)WindowsMessages.WM_PAINT) { //base.WndProc(ref m); if (!Enabled || Focused || Text != "") return; // Prepare for drawing IntPtr hdc = SafeNativeMethods.GetWindowDC(Handle); Graphics g = Graphics.FromHdc(hdc); g.DrawString("Defaultwert…", Font, Brushes.DarkGray, 5, 2); SafeNativeMethods.ReleaseDC(Handle, hdc); } }
Wobei SafeNativeMethods (wie zu sehen) ein paar Interops definiert.
Der "Trick" ist hier base.WndProc(…) nur aufzurufen wenn keine WM_CONTEXTMENU Message vorliegt. Wenn man das weglässt hängt sich das Programm auf.
Funktioniert zwar erst mal unter der Auflage das man kein Kontextmenu mehr nutzen kann, aber das kanns ja dann doch nicht sein oder? Außerdem tritt hier das Flackern auf was schon bekannt ist, aber durch OptimizeDoubleBuffer nicht behoben werden kann, da man dazu auch wieder UserPaint auf true setzen muss. Ein Teufelskreis also ;-)
Kennt dagegen jemand Abhilft oder weis eine bessere Lösung zum zusätzlichen Zeichnen von Text oder Image in eine TextBox?
Gruß, Ulf
Antworten
-
Hallo Ulf,
ich konnte das Problem mit dem Kontextmenü nicht nachvollziehen. Der Code unten ruft zusätzlich zum Selbstgemalten die DefWndProc aufgerufen, damit die Standardroutine ablaufen kann. Auch ein Flackern hält sich in Grenzen, wenn man wie gezeigt den TextRenderer verwendet.
public class TextBoxWithDefault : System.Windows.Forms.TextBox { public TextBoxWithDefault() { } const int WM_PAINT = 15; [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindowDC", ExactSpelling = true)] private static extern IntPtr GetWindowDC(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "ReleaseDC", ExactSpelling = true)] private static extern int ReleaseDC(IntPtr hWnd, HandleRef hDC); protected override void WndProc(ref Message m) { if (m.Msg == WM_PAINT) { if (!String.IsNullOrEmpty(base.Text) || !base.Enabled || base.Focused) { base.WndProc(ref m); } else { base.DefWndProc(ref m); var hDC = new HandleRef(this, GetWindowDC(this.Handle)); try { Debug.WriteLine("TextBoxWithDefault Standardtext"); using (Graphics g = Graphics.FromHdcInternal(hDC.Handle)) { TextRenderer.DrawText(g, "Standard", base.Font, base.ClientRectangle, SystemColors.GrayText, base.BackColor, TextFormatFlags.TextBoxControl | TextFormatFlags.VerticalCenter); } } finally { ReleaseDC(this.Handle, hDC); } } } else { base.WndProc(ref m); } } }
Gruß Elmar- Als Antwort vorgeschlagen Marcel RomaModerator Samstag, 19. Januar 2013 11:41
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 22. Januar 2013 10:49
Alle Antworten
-
Hallo Ulf,
Vielleicht kann das Dir weiterhelfen. http://www.codedblog.com/2007/09/17/owner-drawing-a-windowsforms-textbox/
Gruss,
-
Hallo Ulf,
ich konnte das Problem mit dem Kontextmenü nicht nachvollziehen. Der Code unten ruft zusätzlich zum Selbstgemalten die DefWndProc aufgerufen, damit die Standardroutine ablaufen kann. Auch ein Flackern hält sich in Grenzen, wenn man wie gezeigt den TextRenderer verwendet.
public class TextBoxWithDefault : System.Windows.Forms.TextBox { public TextBoxWithDefault() { } const int WM_PAINT = 15; [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "GetWindowDC", ExactSpelling = true)] private static extern IntPtr GetWindowDC(IntPtr hWnd); [DllImport("user32.dll", CharSet = CharSet.Auto, EntryPoint = "ReleaseDC", ExactSpelling = true)] private static extern int ReleaseDC(IntPtr hWnd, HandleRef hDC); protected override void WndProc(ref Message m) { if (m.Msg == WM_PAINT) { if (!String.IsNullOrEmpty(base.Text) || !base.Enabled || base.Focused) { base.WndProc(ref m); } else { base.DefWndProc(ref m); var hDC = new HandleRef(this, GetWindowDC(this.Handle)); try { Debug.WriteLine("TextBoxWithDefault Standardtext"); using (Graphics g = Graphics.FromHdcInternal(hDC.Handle)) { TextRenderer.DrawText(g, "Standard", base.Font, base.ClientRectangle, SystemColors.GrayText, base.BackColor, TextFormatFlags.TextBoxControl | TextFormatFlags.VerticalCenter); } } finally { ReleaseDC(this.Handle, hDC); } } } else { base.WndProc(ref m); } } }
Gruß Elmar- Als Antwort vorgeschlagen Marcel RomaModerator Samstag, 19. Januar 2013 11:41
- Als Antwort markiert Robert BreitenhoferModerator Dienstag, 22. Januar 2013 10:49
-
Hallo Ulf K.adner,
Ich gehe davon aus, dass die Antwort Dir weitergeholfen hat.
Solltest Du noch "Rückfragen" dazu haben, so gib uns bitte Bescheid.Grüße,
RobertRobert Breitenhofer, MICROSOFT
Bitte haben Sie Verständnis dafür, dass im Rahmen dieses Forums, welches auf dem Community-Prinzip „Entwickler helfen Entwickler“ beruht, kein technischer Support geleistet werden kann oder sonst welche garantierten Maßnahmen seitens Microsoft zugesichert werden können.