c# 为自定义控件添加鼠标双击事件

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c# 为自定义控件添加鼠标双击事件相关的知识,希望对你有一定的参考价值。

最近在用一个厂家提供的控件(c++写的),这个控件只可以响应鼠标右键事件(厂家提供的接口),但是不能响应鼠标双击事件,现在我想在这个控件上添加双击事件(在c#环境下),我该如何扩展这个类?谢谢!

厂家提供的控件都是封装好的,就算你扩展这个类也只能添加功能,不能直接响应双击事件。

但是你可以拦截这个控件的双击消息。

以下代码可加在控件的父窗口(假设为Form1),并在Form1初始化后安装拦截挂钩。同样的方法也可屏蔽那控件的其它消息,如屏蔽它的右键事件。

private const int GWL_WNDPROC = -4;
private const int WM_LBUTTONDOWN=0x0201;
private const int WM_LBUTTONUP=0x0202;
private const int WM_LBUTTONDBLCLK=0x0203;//双击消息

[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, MyWndProc wndProc);
[DllImport("user32.dll", CharSet = CharSet.Auto)]
private static extern IntPtr CallWindowProc(IntPtr wndProc, IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

public delegate IntPtr MyWndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);

private IntPtr OldWndProc = IntPtr.Zero;
private MyWndProc Wpr = null;

private IntPtr MyControlWndProc(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam)

switch (msg)

case WM_LBUTTONDBLCLK://拦截双击消息

/*在这里,你想干什么就干什么*/
.......................
.......................

return (IntPtr)0;
default:
return CallWindowProc(OldWndProc, hWnd, msg, wParam, lParam);



//假设那个控件变量名为 _thatControl

private void InitializeThatControl()

//初始化的时候安装消息拦截
this.Wpr = new MyWndProc(this.MyControlWndProc);
this.OldWndProc = SetWindowLong(_thatControl.Handle, GWL_WNDPROC, Wpr);


public Form1()

InitializeComponent();
InitializeThatControl();//加这句,在Form初始化后安装消息拦截
参考技术A 能看到源码么?
能看到的话继续用c++写
或者添加自定义控件继承这个控件,再重写OnDoubleClick事件
参考技术B 在源代码上加个事件 参考技术C 你没有源代码,怎么加?与提供厂家联系吧。

为自定义控件实现值访问器时,未从事件中的模型获取更新值

【中文标题】为自定义控件实现值访问器时,未从事件中的模型获取更新值【英文标题】:Not getting updated value from model in events when implementing value accessor for custom controls 【发布时间】:2016-09-12 13:35:33 【问题描述】:

我正在关注下面的文章,我正在尝试在与 ngModel 和 ngControl 集成的 Angular 2 中实现自定义控件。

文章:http://almerosteyn.com/2016/04/linkup-custom-control-to-ngcontrol-ngmodel

但是我很难弄清楚在发出事件时如何获取更新的模型值。好像是在事件中使用更新前的模型。

这是一个带有示例的 plunker:

https://plnkr.co/edit/ixK6UxhhWZnkFyKfbgky

我做错了什么?

ma​​in.ts

import bootstrap    from '@angular/platform-browser-dynamic';
import App from './app';

bootstrap(App, [])
  .catch(err => console.error(err));

app.ts

import Component from '@angular/core'
import FORM_DIRECTIVES from "@angular/common";
import CustomInput from './custom-input.component'

@Component(
  selector: 'my-app',
  providers: [],
  template: `
  <form (ngSubmit)="onSave()" #demoForm="ngForm">

   <div class="row info-row">
    <span class="col-xs-12">
    <p><span class="boldspan">Form data:</span>demoForm.value | json</p>
    <p><span class="boldspan">Model data:</span> dataModel</p>
    </span>
    </div>

    <custom-input ngControl="someValue" ref-input (onKeyDown)="onKeyDown(input)" [(ngModel)]="dataModel">Enter data:</custom-input>

  </form>
  `,
  directives: [CustomInput, FORM_DIRECTIVES]
)
export class App 
  dataModel: string = '';

  onKeyDown(event)
    console.log(event._value);
    console.log(this.dataModel);
  

custom-input.component.ts

import Component, Provider, forwardRef, Input, Output, EventEmitter from "@angular/core";
import ControlValueAccessor, NG_VALUE_ACCESSOR, CORE_DIRECTIVES from "@angular/common";

const noop = () => ;

const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR = new Provider(
  NG_VALUE_ACCESSOR, 
    useExisting: forwardRef(() => CustomInput),
    multi: true
  );

@Component(
  selector: 'custom-input',
  template: `
      <div class="form-group">
        <label><ng-content></ng-content>
          <input class="form-control" [(ngModel)]="value" (keydown)="onKeyDownEvent($event)" (blur)="onTouched()">
        </label>
      </div>
  `,
  directives: [CORE_DIRECTIVES],
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
)
export class CustomInput implements ControlValueAccessor

    @Output() onKeyDown: EventEmitter<any> = new EventEmitter();

    //The internal data model
    private _value: any = '';

    //Placeholders for the callbacks
    private _onTouchedCallback: (_:any) => void = noop;

    private _onChangeCallback: (_:any) => void = noop;

    //get accessor
    get value(): any  return this._value; ;

    //set accessor including call the onchange callback
    set value(v: any) 
      if (v !== this._value) 
        this._value = v;
        this._onChangeCallback(v);
      
    

    //Set touched on blur
    onTouched()
      this._onTouchedCallback();
    

    //From ControlValueAccessor interface
    writeValue(value: any) 
      this._value = value;
    

    //From ControlValueAccessor interface
    registerOnChange(fn: any) 
      this._onChangeCallback = fn;
    

    //From ControlValueAccessor interface
    registerOnTouched(fn: any) 
      this._onTouchedCallback = fn;
    

    onKeyDownEvent(event)
      this.onKeyDown.emit(event);
    


【问题讨论】:

【参考方案1】:

我认为问题在于您将自定义输出和注册回调混合在一起。在这种情况下,不需要自定义输出。

您可以利用CustomInput 组件中的ngModelChange 事件来调用_onChangeCallback 回调:

@Component(
  selector: 'custom-input',
  template: `
    <div class="form-group">
      <label><ng-content></ng-content>
        <input class="form-control" [(ngModel)]="value" 
           (ngModelChange)="onModelChange($event)" 
           (keydown)="onKeyDownEvent($event)"
           (blur)="onTouched()">
      </label>
    </div>
`,
(...)
export class CustomInput implements ControlValueAccessor 
  (...)

  onModelChange(value) 
    this.value = value;
    this._onChangeCallback(value);
  

在这种情况下,不再需要您的 getter 和 setter。

您也可能对这篇文章感兴趣(“NgModel 兼容组件”部分):

http://restlet.com/blog/2016/02/17/implementing-angular2-forms-beyond-basics-part-2/

【讨论】:

感谢您提供的信息。我不知道 ngModelChange 以及多么棒的文章。我已经尝试过你提出的建议,这里是一个新的plunkr,但奇怪的是,一旦我删除了 get 和 set,它就不再绑定初始值了。你说我把事情搞混了,但是如果不这样做,怎么可能在组件之外获取更新的模型呢?

以上是关于c# 为自定义控件添加鼠标双击事件的主要内容,如果未能解决你的问题,请参考以下文章

4.为自定义控件添加事件

3.为自定义控件添加属性

C#自定义控件的鼠标事件问题

c# winform 制作自定义控件

C# 做的winform窗体程序把一个Form给为自定义控件?

做WPF页面的时候我想通过C#代码触发自定义控件中的事件怎么做