Onpaint can be used to redraw the work area of a form. There are several ways to draw a workspace.
1. directly implement wm_nccalcsize message Rendering
2. Modify the form to the none Status and intercept wm_nccalcsize to modify the non-workspace size.
3. Modify the form to none to directly simulate the status.
These three methods may have some weaknesses, which may be because I have not found a corresponding solution.
1. After implementation, You need to modify base. controlbox = false, or else the result will appear when the mouse passes.
In fact, we want the following effect:
However, you cannot use the menu in the taskbar,If anyone knows how to solve this problem, I 'd like to thank you.
2. in the second implementation, when maximizing and minimizing the size, I don't know why the form will be automatically scaled down in the title bar defined by wm_nccalcsize. This also has a solution to the compromise, it is to rewrite setboundscore and comment out the content, but in this case, the size of the form cannot be changed in Visual Studio. I would like to thank you for the solution.
Protected Override VoidSetboundscore (IntX,IntY,IntWidth,IntHeight, boundsspecified specified ){// Base. setboundscore (X, Y, width, height, specified );}
3. The third type is of course the best, but the simulated status cannot be directly replaced with a previously written form.
The first and second types are actually a bit similar. The main point is to draw them.
Re-paint non-workspace, which focuses on
Using(Bitmap IMG =NewBitmap (This. Bounds. Width,This. Bounds. Height ))
{Graphics G = graphics. fromimage (IMG );
......
GS. drawimage (IMG, point. Empty );
}
The dual cache is used to draw the image first and then draw the image on the form.
Draw Functions /// <Summary> /// Re-paint non-Workspace /// </Summary> Private Void Ncpaint () {intptr WDC = Common. getwindowdc ( This . Handle ); // Graphics. fromhwnd (this. Handle ); Graphics G = graphics. fromhdc (WDC ); Try {Darwregion (g );} Catch {} Common. releasedc ( This . Handle, WDC );} Private Void Darwregion (Graphics GS ){ If ( This . Formborderstyle = formborderstyle. None) Return ; Using (Bitmap IMG = New Bitmap ( This . Bounds. Width,This . Bounds. Height) {graphics G = graphics. fromimage (IMG ); If (Mousemove = mousemose. None) {graphicspath drawrect = rectx ( New Rectangle (0, 0, This . Bounds. Width, This . Bounds. Height), arc ); // Draw gradient Rectangle rect = New Rectangle (0, 0, This . Bounds. Width, This . Bounds. Height); lineargradientbrush = New Lineargradientbrush (rect, This . _ Colora, This . _ Colorb, 90); drawrect. addrectangle ( New Rectangle (borderwidth, headheight, This . Clientsize. Width, This . Clientsize. Height); G. fillpath (brush, drawrect ); // Draw the icon If (Showicon) g. drawicon ( This . Icon,New Rectangle (borderwidth + 5, (headheight-16)/2, 16, 16 )); // Draw the title Stringformat Sf = New Stringformat (); SF. linealignment = stringalignment. Center; // Locate the region of the title bar Tooltitle = New Rectangle (borderwidth + 23, 0, This . Bounds. Width, headheight); G. drawstring ( This . Text, This . Font, New Solidbrush (This . Forecolor), tooltitle, SF ); // Draw the max. Min close button // G. drawimage (butclose, butclose ); // G. drawimage (butmax, butmax ); // G. drawimage (butmin, butmin ); Drawbutton (g ); // Draw a border G. smoothingmode = smoothingmode. highquality; // High Quality Drawrect = rectx ( New Rectangle (1, 1, This . Bounds. Width-4, This . Bounds. Height-4), ARC-1); G. drawpath ( New Pen (color. fromargb (100, color. White), 1), drawrect ); // Draw the inner border Drawrect = rectx ( New Rectangle (0, 0, This . Bounds. Width-2, This . Bounds. Height-2), ARC-1); G. drawpath ( New Pen (solidcolor, 1), drawrect ); // Draw the outer border } Else { Int I =This . Bounds. Width-3, H = 1; Foreach (Toolbutton In Listbutton ){ If (! A. Start) Continue ; I = I-A. Size. width; rectangle rect = New Rectangle ( New Point (I, H), A. size ); If (A = _ newbutton) {G. fillrectangle ( New Solidbrush (colora), rect); G. drawimage (A. Move, rect );} Else If (A = _ oldbutton) {G. fillrectangle ( New Solidbrush (colora), rect); G. drawimage (A. Default, rect) ;}} Gs. drawimage (IMG, point. Empty );}}
For how to draw the three buttons, refer to the method of rewriting the tabcontrol label in my previous article.
Finally, there are several messages that need to be re-painted.
Non-customer zone refresh /// <Summary>/// Non-customer zone refresh/// </Summary>Private VoidNcupdate () {common. sendmessage (This. Handle ,(Int) Msg. wm_ncpaint, 0, 0 );}
Non-customer zone refresh Switch (M. msg ){ Case ( Int ) Msg. wm_nccalcsize: borderwidth = (This . Bounds. Width- This . Clientsize. width)/2; headheight = This . Bounds. Height- This . Clientsize. Height-borderwidth; mousemove = mousemose. None; // Ncpaint (); Base . Wndproc ( Ref M ); Break ; Case ( Int ) Msg. wm_ncactivate:Base . Wndproc ( Ref M); mousemove = mousemose. None; ncupdate (); Break ; Case ( Int ) Msg. wm_ncpaint: ncpaint (); Break ; Case ( Int ) Msg. wm_nclbuttondown: If (Getmousebutton () = Null ){ Base . Wndproc ( Ref M ); // Console. writeline (1 ); } Break ; Case ( Int ) Msg. wm_nclbuttonup: toolbutton but = getmousebutton (); If (! = Null ) {But. onclick ();} Base . Wndproc ( Ref M ); Break ; Case ( Int ) Msg. wm_ncmousemove: newbutton = getmousebutton (); Base . Wndproc ( Ref M ); Break ; Case ( Int ) Msg. wm_erasebkgnd: Base . Wndproc ( Ref M); ncpaint (); mousemove = mousemose. None; ncupdate (); Break ; Default : Base . Wndproc ( Ref M ); Break ;}
Here, when you click the close button, the message cannot be received by wm_nclbuttondown. After studying for a long time, we found a method to receive the message. In the wm_nclbuttonup event, we can determine whether the message was pressed by the max, Min, close button, if yes, do not executeBase. Wndproc (RefM.
Basically, the principle of form drawing is something like this. If any of you have better suggestions on the above method, you are welcome to discuss it.