Click here to Skip to main content
15,886,110 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
See more:
I'm trying to avoid sending the text inside a TextBox when WM_GETTEXT message is sent to a password TextBox.
The code I've written in the form that contains the TextBox (tbxPw) is the following:

C#
[SecurityPermission(SecurityAction::Demand, Flags=SecurityPermissionFlag::UnmanagedCode)]
virtual void WndProc(Message% m) override
{
    if (m.Msg == WM_GETTEXT)
    {
        char *buff = (char *) m.LParam.ToInt32();
        buff[m.Result.ToInt32()] = 0;
        String^ sTextInside = gcnew String(buff);
        if ( (sTextInside != "") && (sTextInside == this->tbxPw->Text) )
        {
            m.LParam = IntPtr(0);
            return;
        }
    }
    Form::WndProc(m);
}


I tried to debug when windows sends the message WM_GETTEXT and the result is that sTextInside is always an empty string.

Why I can't get the text that WM_GETTEXT message is trying to retrieve?
I tried processing Form::WndProc(m) at the begining and the same result (also I don't know if this should be at the begining or at the end)
Posted

1) sTextInside will be empty in case of (0 == buff) or (0 == buff[0])
2) It is a reaction of your form (not of this->tbxPw)
3) The coming buffer is here to be filled in, not to be read
4) Be sure also you need char and not WCHAR
 
Share this answer
 
Comments
miqmago 25-Mar-11 12:07pm    
Thanks for your answer Eugen,

As I know:
1. (buff != 0) always as (m.LParam != 0), so it means (I suppose..) not an empty buffer?
2. So what should I do to avoid WM_GETTEXT to read the text inside tbxPw? As I know, when EnumChildWindows is called from external application, it passes the handle to each window in the form, including controls created by the window.. Is there any way to catch WndProc from TextBox?
3. Doesn't matter if I call Form::WndProc(m) before I read m.LParam? Then, when is it filled m.LParam? (I thought the app arrives here after preprocess the message)
4. http://msdn.microsoft.com/en-us/library/ms633520%28v=VS.85%29.aspx says lParam is a LPSTR so it is a char * buffer..
Eugen Podsypalnikov 25-Mar-11 12:34pm    
1) Then (0 == buff[0]), in other words the buffer's content is empty
2) You should try to subclass the edit box by your own control with its own reaction for WM_GETTEXT
3) A control does receive the WM_GETTEXT (LPARAM=buffer, WPARAM=its length) to fill the buffer out (it is an answer, so the customer of the text has no answer when the reaction does nothing (!))
4) ...says LPTSTR (not LPSTR)
miqmago 25-Mar-11 12:38pm    
Thanks Eugen,
Option 2 is what I'm doing now.. so I've written a new pwTextBox that encapsulates TextBox with its own WndProc.

What happens now is that if I disble WM_GETTEXT, there is no text inside, so I have to build manually a StringBuilder to get back the text when it is needed! :)
Thanks anyway!!
The solution: (also see http://blog.tcx.be/2008/04/making-your-password-textbox-more.html[^])

C#
#pragma once
#include <Windows.h>
using namespace System;
using namespace System::ComponentModel;
using namespace System::Drawing;
using namespace System::Windows::Forms;
using namespace System::Security::Permissions;
namespace InputForms
{
    /// <summary>Represents a text box control for entering passwords.</summary>
    [ToolboxItem(true), ToolboxBitmap(TextBox::typeid)]
    public ref class pwTextBox : public System::Windows::Forms::TextBox
    {
    public:
        /// <summary>Initializes a new instance of the <see cref="T:pwTextBox" /> class.</summary>
        pwTextBox(void) : TextBox()
        {
            this->_bAccessText = false;
            this->UseSystemPasswordChar = true;
        };
        /// <summary>Gets or sets the current text in the <see cref="T:TextBox"/>.</summary>
        /// <returns>The text displayed in the control.</returns>
        property String^ Text
        {
            virtual String^ get(void) override
            {
                this->_bAccessText = true;
                try { return TextBox::Text; }
                finally { this->_bAccessText = false; }
            }
            virtual void set(String^ value) override
            {
                this->_bAccessText = true;
                try { TextBox::Text = value; }
                finally { this->_bAccessText = false; }
            }
        };
        /// <summary>Gets the length of text in the control.</summary>
        /// <returns>The number of characters contained in the text of the control.</returns>
        property int TextLength
        {
            virtual int get(void) override
            {
                this->_bAccessText = true;
                try { return TextBox::TextLength; }
                finally { this->_bAccessText = false; }
            }
        };
    protected:
        /// <summary>Clean resources.</summary>
        ~pwTextBox()
        {
        }
        [SecurityPermission(SecurityAction::Demand, Flags=SecurityPermissionFlag::UnmanagedCode)]
        virtual void WndProc(Message% m) override
        {
            switch (m.Msg)
            {
                case WM_GETTEXT:
                case WM_GETTEXTLENGTH:
                    if (!this->_bAccessText)
                    {
                        m.Result = IntPtr::Zero;
                        return;
                    }
                    else break;
                case EM_SETPASSWORDCHAR: return;
            }
            TextBox::WndProc(m);
        };
    private:
        bool _bAccessText;
    };
}
 
Share this answer
 
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900