简体   繁体   English

如何在不可设置的控件中覆盖wndProc

[英]How to override wndProc in a non settable control

I have a XtraGrid and some columns can get masked depending on the value of another column. 我有一个XtraGrid ,根据另一列的值,某些列可能会被掩盖。
I managed to achieve it by seting the mask in the editor in the CustomRowCellEdit event. 我设法通过在CustomRowCellEdit事件中的编辑器中设置掩码来实现此目的。

Snipet below: 下面的片段:

private void myGridView_CustomRowCellEdit(object sender, CustomRowCellEditEventArgs e)
{
    if (e.Column.FieldName == "MyTargetField")
    {
        GridView gv = sender as GridView;
        var typeValue = gv.GetRowCellValue(e.RowHandle, gv.Columns["MaskOrNotDependsOnThisField"]);

        if (typeValue == DynamicMask)
        {

            var maskToApply = GetMaskForThisValue(gv.GetRowCellValue(e.RowHandle, gv.Columns["MyTargetField"]));

            RepositoryItemTextEdit riMaskedTextEdit = new RepositoryItemTextEdit();
            riMaskedTextEdit.Mask.MaskType = MaskType.Simple;
            riMaskedTextEdit.Mask.UseMaskAsDisplayFormat = true;
            riMaskedTextEdit.Mask.SaveLiteral = false;
            riMaskedTextEdit.Mask.EditMask = maskToApply;
            e.RepositoryItem = riMaskedTextEdit;
            //riMaskedTextEdit.KeyDown += EditorKeyDownDinamicMask;
        }
    }
}

It worked like a charm but some masks can be dynamic (hey I don't make the requeriments!). 它的工作原理就像是一种魅力,但某些遮罩可能是动态的(嘿,我不提出要求!)。
So I uncomment that event handler line and created a KeyDownEventHandler . 所以我取消注释该事件处理程序行,并创建了一个KeyDownEventHandler

Let's say my mask changes as user keeps typing like: 假设我的遮罩随着用户不断输入而变化,例如:

999.999 for 6 digits 999.999(6位数字)

999.999-9 for 7 digits 999.999-9(7位数字)

999.(999)/99 for 8 digits 999.(999)/ 99 8位数字

Note I need to use KeyDown because the mask can prevent the ValueChanged event to fire. 注意我需要使用KeyDown,因为该掩码可以防止ValueChanged事件触发。
I handled the keydown and managed to put this thing to work fine. 我处理了按键,并设法将其正常工作。

Question is: How to handle Paste events? 问题是: 如何处理粘贴事件? (from both keyboard and mouse paste events) (来自键盘和鼠标粘贴事件)

I know how to override wndProc in a control, I already did it a few times before. 我知道如何在控件中覆盖wndProc ,我已经做过几次了。
Problem here is RepositoryItemTextEdit class is not a control with a wndProc to override. 这里的问题是RepositoryItemTextEdit类不是带有wndProc要覆盖的控件。
I digged a bit and found the above class has a 我挖了一下,发现上面的课有一个

public TextEdit OwnerEdit { get; }

And that is the real guy handling the events. 那是处理事件的真正的家伙。
Unfortunately devxpress left it as a non settable member. 不幸的是,devxpress将其保留为不可设置的成员。

Right now user cannot replace the 999.999 value with a 999.999-9 in copy paste because the mask truncates the pasted value. 现在,用户无法使用复制粘贴中的999.999-9替换999.999值,因为掩码会截断粘贴的值。
Note it also prevents the ValueChaged event to fire 请注意,这也会阻止ValueChaged事件触发

RepositoryItemTextEdit class is used to hold the properties for in-place instance of TextEdit class. RepositoryItemTextEdit类用于保存TextEdit类的就地实例的属性。 Technically TextEdit class is box which holds the instance of TextBoxMaskBox class. 从技术上讲, TextEdit类是一个框,其中保存TextBoxMaskBox类的实例。 TextBoxMaskBox class is inherited from System.Windows.Forms.TextBox class. TextBoxMaskBox类继承自System.Windows.Forms.TextBox类。
So, you can create your own RepositoryItemTextEdit , TextEdit and TextBoxMaskBox descendants and override WndProc method in your own TextBoxMaskBox descendant. 因此,您可以创建自己的RepositoryItemTextEditTextEditTextBoxMaskBox后代,并在自己的TextBoxMaskBox后代中重写WndProc方法。
Here is example: 这是示例:

[UserRepositoryItem("RegisterPasteHandlerEdit")]
public class RepositoryItemPasteHandlerEdit : RepositoryItemTextEdit
{
    static RepositoryItemPasteHandlerEdit()
    {
        RegisterPasteHandlerEdit();
    }

    static private readonly object EventPaste;

    public const string CustomEditName = "PasteHandlerEdit";

    public RepositoryItemPasteHandlerEdit() { }

    public override string EditorTypeName => CustomEditName;

    public static void RegisterPasteHandlerEdit()
    {
        Image img = null;
        EditorRegistrationInfo.Default.Editors.Add(new EditorClassInfo(CustomEditName, typeof(PasteHandlerEdit), typeof(RepositoryItemPasteHandlerEdit), typeof(TextEditViewInfo), new TextEditPainter(), true, img));
    }

    public override void Assign(RepositoryItem item)
    {
        BeginUpdate();
        try
        {
            base.Assign(item);
            var source = item as RepositoryItemPasteHandlerEdit;
            if (source == null) return;

            Events.AddHandler(EventPaste, source.Events[EventPaste]);
        }
        finally
        {
            EndUpdate();
        }
    }

    public event PasteEventHandler OnPaste
    {
        add
        {
            Events.AddHandler(EventPaste, value);
        }
        remove
        {
            Events.RemoveHandler(EventPaste, value);
        }
    }

    protected internal void RaiseOnPaste(PasteEventArgs e)
    {
        if (IsLockEvents)
            return;

        var handler = (PasteEventHandler)Events[EventPaste];
        handler?.Invoke(GetEventSender(), e);
    }
}

[ToolboxItem(true)]
public class PasteHandlerEdit : TextEdit
{
    static PasteHandlerEdit()
    {
        RepositoryItemPasteHandlerEdit.RegisterPasteHandlerEdit();
    }

    public PasteHandlerEdit() { }

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
    public new RepositoryItemPasteHandlerEdit Properties => base.Properties as RepositoryItemPasteHandlerEdit;

    public override string EditorTypeName => RepositoryItemPasteHandlerEdit.CustomEditName;

    protected override TextBoxMaskBox CreateMaskBoxInstance() => new PasteHandlerMaskBox(this);

    protected override void CreateMaskBox()
    {
        base.CreateMaskBox();

        var pasteHandlerMaskBox = MaskBox as PasteHandlerMaskBox;
        pasteHandlerMaskBox.OnPaste += PasteHandlerMaskBox_OnPaste;
    }

    private void PasteHandlerMaskBox_OnPaste(object sender, PasteEventArgs e) => Properties.RaiseOnPaste(e);
}

public class PasteHandlerMaskBox : TextBoxMaskBox
{
    private const int WM_PASTE = 0x0302;

    public PasteHandlerMaskBox(TextEdit ownerEdit) : base(ownerEdit) { }

    public event PasteEventHandler OnPaste;

    protected override void WndProc(ref Message msg)
    {
        if (msg.Msg == WM_PASTE)
        {
            var e = new PasteEventArgs();

            OnPaste?.Invoke(this, e);

            if (e.Cancel)
                return;
        }

        base.WndProc(ref msg);
    }
}

public class PasteEventArgs : CancelEventArgs
{
    public PasteEventArgs() { }
    public PasteEventArgs(bool cancel) : base(cancel) { }

    public string Text => Clipboard.GetText();
}

public delegate void PasteEventHandler(object sender, PasteEventArgs e);

In this example the OnPaste event is added to RepositoryItemPasteHandlerEdit class. 在此示例中, OnPaste事件被添加到RepositoryItemPasteHandlerEdit类。 You can use this: 您可以使用此:

private void repositoryItemPasteHandlerEdit1_OnPaste(object sender, PasteEventArgs e)
{
    MessageBox.Show(e.Text);

    if (...) // Perform some checks.
        e.Cancel = true;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM