\

Školení Návrhové vzory, OOP a UML


 Wednesday, February 04, 2009
Textbox nepodporující výběr textu a další specialitky

Někdy se hodí mít textbox, u kterého je skrytý "caret" (netuší někdo, jak se termín caret překládá - pouze kurzor?) a současně nepodporuje označování textu. Také můžete chtít, aby se textbox choval podobně jako při nastavení vlastnosti ReadOnly na true, ale bez "zašedlého" zobrazení textboxu, což je  většinou nechtěný průvodní jev textových polí označených pouze pro čtení.

Kód je pro Compact .Net Framework, nic vám ale nebrání přenést jej na "velký" NF. Ke zpracování Windows zpráv je použita třída NativeWindow, která je součástí OpenNetCF frameworku. Opravdu jen tato podivná sekvence zpracování Windows zpráv byla v CNF ta pravá.

 

using System;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Windows.Forms;
using OpenNETCF.Windows.Forms;

namespace HideCaret
{
    public class NativeTxtWrapper : NativeWindow
    {
        [DllImport("CoreDll.dll")]
        private static extern bool ShowCaret(IntPtr hWnd);

        [DllImport("CoreDll.dll")]
        private static extern bool HideCaret(IntPtr hWnd);

        private TextBox m_txtBox;
        private bool m_hasFullFocus;
        
        
        private const int WM_LBUTTONDOWN = 0x201;
        private const int WM_KEYDOWN = 0x0100;
        private const int WM_MOUSEMOVE = 0x0200;
        private const int WM_CHAR = 0x0102;
        private const int WM_COMMAND = 0x0111;
        private const int WM_LBUTTONUP = 0x0202;
        private const int WM_LBUTTONDBLCLK = 0x0203;
        private const int WM_PAINT = 0x000F;
        private const int WM_KILLFOCUS = 0x0008;
        private const int WM_SETFOCUS  = 0x0007;
        




        




        public NativeTxtWrapper(TextBox txtBox)
        {
            init(txtBox);
            m_hasFullFocus = false;
        }
        private void init(TextBox txtBox)
        {
            if (txtBox == null)
            {
                throw new ArgumentNullException("txtBox");
            }

            if (txtBox.Handle != IntPtr.Zero)
            {

                AssignHandle(txtBox.Handle);
            }

            txtBox.HandleCreated += ((sender, e) => AssignHandle(((Form)sender).Handle));
            txtBox.HandleDestroyed += ((sender, e) => ReleaseHandle());
            m_txtBox = txtBox;
        }


        protected override void WndProc(ref Microsoft.WindowsCE.Forms.Message m)
        {
            if (m.Msg == WM_CHAR)
            {
                m_hasFullFocus = true;
            }

            if (m.Msg == WM_MOUSEMOVE || m.Msg == WM_LBUTTONDBLCLK)
            {
                return;
            }
            
            if (((m.Msg == WM_LBUTTONUP) ||
                (m.Msg == WM_LBUTTONDOWN)) && m_hasFullFocus)
            {
                return;
            }
            if (m.Msg == WM_SETFOCUS)
            {
                base.WndProc(ref m);
                HideCaret(m_txtBox.Handle);
                return;
                //m_hasFocus = false;    
            }
            
            if (m.Msg == WM_KILLFOCUS)
            {
                m_hasFullFocus = false;
            }

            base.WndProc(ref m);
        }

    }
}

   

Jestliže chcete textbox pouze pro čtení, stačí  nepředat ke zpracování bázové třídě (base.WndProc) zprávu WM_CHAR.

 

Objektem NativeTxtWrapper lze oddekorovat jakýkoli textbox, nebo můžete vytvořit potomka třídy Textbox, který před klienty třídy skryje použití objektu NativeTextWrapper

private void Form1_Load(object sender, EventArgs e)
        {
            m_wrapper = new NativeTxtWrapper(textBox1);
            textBox1.Focus();
            
        }

Podobnou třídu mám i pro nativní projekty psané v MFC, možná se někomu z vás bude hodit. Přepsat kód do Windows API z MFC je také trivální.

 

#pragma once

#include "afxwin.h"

 

class CTextBoxEx :

    public CEdit

{

 

private:

    bool m_hasFullFocus;

 

public:

 

    CTextBoxEx(void);

    ~CTextBoxEx(void);

    virtual LRESULT WindowProc(UINT message, WPARAM wparam, LPARAM lparam);

 

};

#include "StdAfx.h"

#include "TextBoxEx.h"

 

 

 

CTextBoxEx::CTextBoxEx(void) : m_hasFullFocus(false)

{

}

 

CTextBoxEx::~CTextBoxEx(void)

{

}

 

LRESULT CTextBoxEx::WindowProc(UINT message, WPARAM wparam, LPARAM lparam)

{

 

//Readonly textbox

            if (message == WM_CHAR)

            {

                return 1;

            }

//end Readonly textbox

 

            POINT mousePoint;

            GetCursorPos(&mousePoint);

            ScreenToClient(&mousePoint);

            RECT clientRect;

            GetClientRect(&clientRect);

            BOOL isMouseInRect = PtInRect(&clientRect, mousePoint);

 

            if (((message == WM_MOUSEMOVE) || (message == WM_LBUTTONDBLCLK)) && isMouseInRect)

            {

                return 1;

            }

 

            if (((message == WM_LBUTTONUP) ||

                (message== WM_LBUTTONDOWN)) && m_hasFullFocus && isMouseInRect)

            {

                return 1;

            }

 

            if (message == WM_SETFOCUS)

            {              

                m_hasFullFocus = true;

                HideCaret();

                return 1;

 

            }

 

            if (message == WM_KILLFOCUS)

            {

                m_hasFullFocus = false;

            }

 

            return CEdit::WindowProc(message, wparam, lparam);

 

}



Wednesday, February 04, 2009 4:52:26 PM (Central Europe Standard Time, UTC+01:00)       
Comments [6]  .NET Framework | Compact .Net Framework | Nativní kód | Windows Forms