WPF custom control -- use Win32 Control

Source: Internet
Author: User

Although WPF is very powerful, Win32 has done a good job and we can take it with us.

 

I. How to Create a Win32 Control

 

1. First define a wndclassex class, refer to http://baike.baidu.com/view/1750396.html? TP = 0_11

 Wndclassex Wndclsex = New  Wndclassex (); Wndclsex. INIT (); // (Uint) Marshal. sizeof (this); get the class size Wndclsex. Style = Wndclasstype . Cs_vredraw | Wndclasstype . Cs_hredraw; // Window style Wndclsex. lpfnwndproc = New  Wndprocdelegate ( User32dll . Defwindowproc ); // Process messages. The default message is used here. Wndclsex. cbclsextra = 0; // Specify the number of additional bytes that follow the window class structure Wndclsex. cbwndextra = 0; // If an applicationProgramWhen registering a dialog box class with class pseudoinstructions in the resource, you must set this member to dlgw.wextra. Wndclsex. hinstance = Kernal32dll . Getmodulehandle ( Null ); // Module handle Wndclsex. hicon = Intptr . Zero; // Icon handle Wndclsex. hiconsm = Intptr . Zero;// Small icon associated with the window class. If the value is null. Then, the icon in hcursor is converted to an appropriate small icon. Wndclsex. hcursor = Intptr . Zero; // Cursor handle Wndclsex. hbrbackground = Intptr . Zero; // Specifies the background paint brush handle. Wndclsex. lpszclassname = m_wndclsname; // Define your own class name, such as curry or XXX Wndclsex. lpszmenuname = Null ; // Menu name 

2. Registration class. If the returned value is not 0, the registration is successful.

BoolSuccess =User32dll. Registerclassex (RefWndclsex )! = 0;Debug. Assert (success,"Registerwndclass failed .");

3. Create a window, see http://baike.baidu.com/view/1080304.htm

 Intptr Windowhandle = User32dll . Createmediawex ( Extendedwndstyle . Ws_ex_layoutrtl // Extended Style , M_wndclsname // The name just registered , Null  // Form name ,Wndstyle . Ws_visible | Wndstyle . Ws_child // Subform , This . Left // X coordinate , This . Top // Y coordinate , This . Width // Width , This . Height // Height , This . Parent. Handle // Parent object handle ,Intptr . Zero // Context menu handle , Kernal32dll . Getmodulehandle ( Null ) // Instance handle , Intptr . Zero // Pointer to a value, which is passed to the window wm_create message ); Debug . Assert ( User32dll . Iswindow (define whandle ), "Createappswex failed ." );

 

If you want to see the style information of other windows, you can use the spy ++ tool.

 

4. display window

User32dll. Showwindow (FIG ,(Int)(This. Visible?Windowshowstyle. Show:Windowshowstyle. Hide ));

5. Destruction window, logout class

 
User32dll. Destroywindow (windowhandle); then whandle =Intptr. Zero;User32dll. Unregisterclass (m_wndclsname,Kernal32dll. Getmodulehandle (Null));

 

 

2. Place the Win32 control in WPF

 

In fact, in WPF, this is just the illusion of vision. Our top-level windows, such as Windows, and popup, also useCreatemediawex(Of course, the menu is also createmediawex). Therefore, the parent of the Win32 control we created is generally a top-level window, intptr hwnd = (hwndsource) presentationsource. fromvisual (uielement )). handle; the obtained handle is the top-level form handle, because the WPF and GDI + paintlayer are different, the two are unable to interact with pixels due to the "airspace" problem. For details, see http://msdn.microsoft.com/zh-cn/library/aa970688.as.

In the Win32 era sometimes form into irregular transparent graphics may do, here also recorded: refer to the self http://www.codeproject.com/KB/dialog/SemiTranDlgWithCtrls.aspx

In XP and later versions, you can use updatelayeredwindow to create a window with an alpha channel similar to a PGN image.

    • Set the window extension style to extendedwndstyle. ws_ex_layered | extendedwndstyle. ws_ex_transparent | extendedwndstyle. ws_ex_noactivate. In C #, you can set exstyle by reloading the createparams attribute.
    • Use user32dll. getdc to obtain the DC of the window
    • Build a memory DC with gdi32dll. createcompatibledc
    • Use gdi32dll. gdipcreatehbitmapfrombitmap to create a device-independent GDI image and allocate memory for the image. in C #, use the bitmap instance method gethbitmap (color. fromargb (0 ).
    • Use gdi32dll. SelectObject to place the GDI image to the memory created by gdi32dll. createcompatibledc.
    • Of course, you can also use gdi32dll. gdipcreatefromhdc obtains the graphics object. You can use graphics in C. fromhdcinternal draws some words, circles, or images on it. Of course, you can also draw them directly on the image.
    • Create a blendfunction and use alphablend to control the transparency of Bitmap.
    • Use user32dll. updatelayeredwindow to update the display.

The above steps show you a transparent background image, and then place a form with actual controls on it, adjust the form style to no style, and set the background to transparent, in this way, there will be two forms that look stupid but are often used. Of course, you should also note that when you drag a form, you have to move the other form. When you hide the form, both are hidden. When you close the form, of course, both are closed.

There are other ways to create an irregular form, such as the path method, and you can use a self-painted Control for layers. Now the simplest irregular window is WPF ^-^.

 

The same is true in WPF. Win32 controls are the top display controls mentioned above. When WPF moves, we move Win32 controls, in addition to the basic movement, we also need to handle the switch of tab keys, as well as some help keys, shortcuts, and other messages. It sounds troublesome, but it doesn't matter. There is a class in WPF.HwndhostIt has been encapsulated for us. We only need to inherit the class and then reloadBuildwindowcoreFunction. Return the handleref of the created control.

Http://msdn.microsoft.com/en-us/library/ms752055.aspx

In addition to Microsoft's practice in the above Link, what about winform controls? Naturally, it is simpler (whereUsercontrol1Inherit from usercontrol for the winform Control)

Protected overrideHandlerefBuildwindowcore (HandlerefHwndparent ){Usercontrol1Usercontrol =NewUsercontrol1(); Usercontrol. Height = hostheight; usercontrol. width = hostwidth;User32dll. Setparent (usercontrol. Handle, hwndparent. Handle );Return newHandleref(Usercontrol, usercontrol. Handle );}

You can also reload wndproc in hwndhost to obtain messages.DestroywindowcoreTo destroy the form and some unmanaged things.

 

Iii. Transform

 

WPF cannot perform transform operations on non-WPF controls, but some transform operations can be performed on custom controls that expose messages. In general, transform is the implementation of matrix, for matrix, let's first make a question:

It is known that the center of the circle O (0, 0) has a p (x, y) on the coordinate axis, and the op a degree is rotated counter-clockwise so that the point P reaches p1 (x1, Y1), with X, Y indicates the coordinates of Point P1.

Solution: it is clear that P1 o is equal to Po, which is an arbitrary M point on the X axis. Assume that our mop is degrees B, and the p1op is a degree.

So

X1 = Po * Cos (A + B)

Y1 = Po * sin (A + B)

Expand

X1 = Po * Cos (a) * Cos (B)-po * sin (a) * sin (B)

Y1 = Po * sin (a) * Cos (B) + Po * Cos (a) * sin (B)

Because

X = Po * Cos (B)

Y = Po * sin (B)

The above formula

X1 = x * Cos (a)-y * sin ()

Y1 = y * Cos (A) + x * sin ()

If you forget enough about trigonometric functions, please refer

Http://zh.wikipedia.org/w/index.php? Title = trigonometric function & variant = ZH-CN

Use a matrix to represent vertices before moving

X1 [1 * X, 0 * Y]

Y1 [0 * X, 1 * Y]

Changed

X Y

X1 [cos (A),-sin (a)]

Y1 [cos (A), sin (a)]

Of course, we may also have an offset, for example, moving two units to the vertical direction, and moving one unit to the positive unit, that is, an affine transformation.

X1 [cos (A),-sin (a)]

Y1 [cos (A), sin (a)]

Z [1, 2]

For convenience of changes, we also add a column so that we can still get the above translation.

[1, 0, 0] * X1 [cos (A),-sin (A), 0]

[0, 1] * Y1 [cos (A), sin (A), 0]

[1, 1] * Z [0, 0, 1]

Note: In the matrix multiplication, A * B is not equal to B *.

Http://zh.wikipedia.org/w/index.php? Title = Transformation Matrix & variant = ZH-CN #. e4.bb. bf. e5.b0.84. e5.8f. 98. e6.8d. A2

Http://zh.wikipedia.org/w/index.php? Title = Matrix & variant = ZH-CN

From the above, Do you think matrix is a point change? If you rotate every point in the image counterclockwise, the image will be skewed, you can simulate the effects of rotatetransform, scaletransform, skewtransform, and translatetransform in WPF.

For the current matrix in WPF, you can obtain matrix m = presentationsource. fromvisual (this). compositiontarget. transformtodevice;

 

4. Message notification

 

With this knowledge, we can use matrix as a parameter to send a Win32 custom drawing so that it can be rotated and changed together. For unmanaged controls, we usually useSendmessageTo transmit messages. Here we use winform as an example.

Let's take a look at the example.

 

Public structCopydatastruct{/// <Summary> ///Data Length/// </Summary>Public intCbdata;/// <Summary> ///First Data address pointer/// </Summary>PublicIntptrLpdata ;}

 Private void Sendmessage () {system. Drawing. drawing2d. Matrix Matrix = New System. Drawing. drawing2d. Matrix ();Binaryformatter Formatter = New  Binaryformatter (); Byte [] Datas; Using (System. Io. Memorystream Mstream = New System. Io. Memorystream () {Formatter. serialize (mstream, matrix); datas = mstream. toarray ();} Int Length = datas. length; Intptr PTR = Marshal . Allochglobal (length );Marshal . Copy (datas, 0, PTR, length ); Copydatastruct Data = New  Copydatastruct (); Data. cbdata = length; data. lpdata = PTR; sendmessage (hwndlistbox, 700, 0, Ref Data ); Marshal . Freehglobal (PTR );}

 Protected override void Wndproc ( Ref  Message M ){ Base . Wndproc ( Ref M );If (M. MSG = 700 ){ Copydatastruct Data = New  Copydatastruct (); Data = ( Copydatastruct ) M. getlparam (data. GetType ()); Byte [] Datas = New byte [Data. cbdata]; Marshal . Copy (data. lpdata, datas, 0, Data. cbdata ); Binaryformatter Formatter = New  Binaryformatter ();Using (System. Io. Memorystream Mstream = New System. Io. Memorystream (Datas )){ // Obtain the object  Object OBJ = formatter. deserialize (mstream );}}}

 

Of course, if you are in trouble, you can also put the two values in wparam and lparam for transmission (this method is not recommended ).

Irregular window case message transmission case

Reprinted please note

 

PS: in fact, these are all from the 10458228 cluster owners in the last month.FerrariThanks again for your enthusiasm.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.