Learn to do c # skin beautification (7) -- form skin replacement

Source: Internet
Author: User
Tags transparent color
Preface

This series has not been updated for a long time. It seems that the previous one was released in July. Well, I don't feel sorry. Let's start introducing today's content! Here, we will illustrate that all the skin replacements implemented this time are based on textures, and they cannot be used to adjust the color or even customize the image as the background like QQ. If you already have experience in this area, the following content may not be suitable for you.If you are interested in this article, please refer to the final download source code for reference. If you have not read any previous articles in this series, please refer to them here. The content of this article is based on those articles!

Texture skin replacement is to use different pictures to draw different backgrounds, and finally form an overall style appearance of the interface (I think so, if you do not welcome to make a brick! ). You only need to record the position and size information of each background image, load the image and information during skin replacement, and draw them to the background for skin replacement. Easy to use ~~

Final:

Skin replacement implementation

The above is just a simple explanation of the skin replacement principle. The following skin replacement flowchart may help you better understand it:

 

The above four processes correspond to the four main methods in the actual class: ReadIniFile, CaculatePartLocation, ReadBitmap, and DrawBackground. Let's look at it one by one:

ReadIniFile

This method is mainly used to read skin configuration information. What? What is the length of configuration information? Let's take a look. I understand all the annotations. I believe everyone understands them! I am not so arrogant (someone said I wrote too long last time, but I was so worried, huh, huh)

This is an INI configuration file. There are many ways to read and write INI files online. I encapsulated them into the ReadIniValue and WriteIniValue methods. The information read is stored in the background block variables. The background block mentioned here is the nine areas of the interface described in the previous article. If you do not know about it, you can refer to the previous article in this series. A background block is a class that inherits from the partbase base class. The partbase class defines several variables and several methods in the configuration file. You can view the variables and methods in the source code, which is not complex.

Code private bool ReadIniFile (string skinFolder) {try {string filePath = skinFolder + "\ config. ini "; // top _ topLeft. height = _ topMiddle. height = _ topRight. height = int. parse (IniHelper. readIniValue (filePath, "Main", "Top_Height"); _ topLeft. width = int. parse (IniHelper. readIniValue (filePath, "Main", "TopLeft_Width"); _ topRight. width = int. parse (IniHelper. readIniValue (filePath, "Main", "TopRight_Width"); // bottom _ bottomLeft. height = _ bottomMiddle. height = _ bottomRight. height = int. parse (IniHelper. readIniValue (filePath, "Main", "Bottom_Height"); _ bottomLeft. width = int. parse (IniHelper. readIniValue (filePath, "Main", "BottomLeft_Width"); _ bottomRight. width = int. parse (IniHelper. readIniValue (filePath, "Main", "BottomRight_Width"); // 中_centerleft. width = int. parse (IniHelper. readIniValue (filePath, "Main", "MiddleLeft_Width"); _ centerRight. width = int. parse (IniHelper. readIniValue (filePath, "Main", "MiddleRight_Width"); minButton. width = int. parse (IniHelper. readIniValue (filePath, "Main", "MinButton_Width"); minButton. height = int. parse (IniHelper. readIniValue (filePath, "Main", "MinButton_Height"); minButton. XOffset = int. parse (IniHelper. readIniValue (filePath, "Main", "MinButton_X"); minButton. top = int. parse (IniHelper. readIniValue (filePath, "Main", "MinButton_Y"); maxButton. width = int. parse (IniHelper. readIniValue (filePath, "Main", "MaxButton_Width"); maxButton. height = int. parse (IniHelper. readIniValue (filePath, "Main", "MaxButton_Height"); maxButton. XOffset = int. parse (IniHelper. readIniValue (filePath, "Main", "MaxButton_X"); maxButton. top = int. parse (IniHelper. readIniValue (filePath, "Main", "MaxButton_Y"); closeButton. width = int. parse (IniHelper. readIniValue (filePath, "Main", "CloseButton_Width"); closeButton. height = int. parse (IniHelper. readIniValue (filePath, "Main", "CloseButton_Height"); closeButton. XOffset = int. parse (IniHelper. readIniValue (filePath, "Main", "CloseButton_X"); closeButton. top = int. parse (IniHelper. readIniValue (filePath, "Main", "CloseButton_Y"); selectSkinButton. width = int. parse (IniHelper. readIniValue (filePath, "Main", "selectSkinButton_Width"); selectSkinButton. height = int. parse (IniHelper. readIniValue (filePath, "Main", "selectSkinButton_Height"); selectSkinButton. XOffset = int. parse (IniHelper. readIniValue (filePath, "Main", "selectSkinButton_X"); selectSkinButton. top = int. parse (IniHelper. readIniValue (filePath, "Main", "selectSkinButton_Y"); return true ;}catch {return false ;}}

 

 

CaculatePartLocation

 In this method, the size and position of each background block are calculated based on the width and height of the current form and the read configuration information. Note the order of calculation in the method. First, the upper left corner and then the middle corner in the upper right corner. The middle width is variable in order to realize the form's scalability. Next is the lower left and lower right, and the end is the middle. I put a panel in the content area in the middle, and its size can be changed. The specific size and position depend on the calculation result. Another function of panel is to better set the layout of the control placed in it without having to care about the upper and lower borders.

Code private void CaculatePartLocation () {// top _ topLeft. X = 0; _ topLeft. Y = 0; _ topRight. X = Width-_ topRight. width; _ topRight. Y = 0; _ topMiddle. X = _ topLeft. width; _ topMiddle. Y = 0; _ topMiddle. width = Width-_ topLeft. width-_ topRight. width; // center part _ centerLeft. X = 0; _ centerLeft. Y = _ topLeft. height; _ centerLeft. height = Height-_ topLeft. height-_ bottomLeft. height; _ centerRight. X = Width-_ cent ErRight. width; _ centerRight. Y = _ topRight. height; _ centerRight. height = Height-_ topLeft. height-_ bottomLeft. height; _ centerMiddle. X = _ centerLeft. width; _ centerMiddle. Y = _ topMiddle. height; _ centerMiddle. width = Width-_ centerLeft. width-_ centerRight. width; _ centerMiddle. height = Height-_ topMiddle. height-_ bottomMiddle. height; // bottom _ bottomLeft. X = 0; _ bottomLeft. Y = Height-_ bottomLeft. he Ight; _ bottomRight. X = Width-_ bottomRight. width; _ bottomRight. Y = Height-_ bottomRight. height; _ bottomMiddle. X = _ bottomLeft. width; _ bottomMiddle. Y = Height-_ bottomMiddle. height; _ bottomMiddle. width = Width-_ bottomLeft. width-_ bottomRight. width; // button position if (MaximizeBox & MinimizeBox) // allows maximization and minimizes {maxButton. left = Width-maxButton. width-maxButton. XOffset; minButton. left = Width-minBu Tton. Width-minButton. XOffset; selectSkinButton. Left = Width-selectSkinButton. Width-selectSkinButton. XOffset;} if (MaximizeBox &&! MinimizeBox) // The {maxButton. left = Width-maxButton. width-maxButton. XOffset; selectSkinButton. left = Width-selectSkinButton. width-minButton. XOffset; minButton. top =-60;} if (! MaximizeBox & MinimizeBox) // maximum allowed {maxButton. top =-60; minButton. left = Width-maxButton. XOffset-minButton. width; selectSkinButton. left = Width-selectSkinButton. width-minButton. XOffset;} if (! MaximizeBox &&! MinimizeBox) // It is not allowed to maximize, minimizing {minButton. top =-60; maxButton. top =-60; selectSkinButton. left = Width-selectSkinButton. width-maxButton. XOffset;} if (! _ ShowSelectSkinButton) {selectSkinButton. top =-60;} closeButton. left = Width-closeButton. width-closeButton. XOffset; // content panel position and size contentPanel. top = _ centerMiddle. y; contentPanel. left = _ centerMiddle. x; contentPanel. width = _ centerMiddle. width; contentPanel. height = _ centerMiddle. height ;}

 

 

ReadBitmap

This method is used to load background images for skin use. You can see the code and there is nothing to talk about.

Code private void ReadBitmap (string skinFolder) {// read the required transparent color value int r = int. parse (IniHelper. readIniValue (skinFolder + "\ config. ini "," Main "," TransparentColorR "); int g = int. parse (IniHelper. readIniValue (skinFolder + "\ config. ini "," Main "," TransparentColorG "); int B = int. parse (IniHelper. readIniValue (skinFolder + "\ config. ini "," Main "," TransparentColorB "); Color trans = Color. fromArgb (r, g, B); TransparencyKey = trans; // transparent processing _ topLeft. backgroundBitmap = Image. fromFile (skinFolder + "\ TopLeft.bmp") as Bitmap; _ topMiddle. backgroundBitmap = Image. fromFile (skinFolder + "\ TopMiddle.bmp") as Bitmap; _ topRight. backgroundBitmap = Image. fromFile (skinFolder + "\ TopRight.bmp") as Bitmap; _ centerLeft. backgroundBitmap = Image. fromFile (skinFolder + "\ MiddleLeft.bmp") as Bitmap; _ centerMiddle. backgroundBitmap = Image. fromFile (skinFolder + "\ Middle.bmp") as Bitmap; _ centerRight. backgroundBitmap = Image. fromFile (skinFolder + "\ MiddleRight.bmp") as Bitmap; _ bottomLeft. backgroundBitmap = Image. fromFile (skinFolder + "\ BottomLeft.bmp") as Bitmap; _ bottomMiddle. backgroundBitmap = Image. fromFile (skinFolder + "\ BottomMiddle.bmp") as Bitmap; _ bottomRight. backgroundBitmap = Image. fromFile (skinFolder + "\ BottomRight.bmp") as Bitmap; minButton. readButtonImage (skinFolder + "\ MinNormal.bmp", skinFolder + "\ MinMove.bmp", skinFolder + "\ MinDown.bmp"); maxButton. readButtonImage (skinFolder + "\ MaxNormal.bmp", skinFolder + "\ MaxMove.bmp", skinFolder + "\ MaxDown.bmp"); closeButton. readButtonImage (skinFolder + "\ CloseNormal.bmp", skinFolder + "\ CloseMove.bmp", skinFolder + "\ CloseDown.bmp"); selectSkinButton. readButtonImage (skinFolder + "\ SelectSkinNormal.bmp", skinFolder + "\ SelectSkinMove.bmp", skinFolder + "\ SelectSkinDown.bmp ");}

 

DrawBackground

All the previous items are ready. Now you can draw the background. Where can I call it? Of course, it is in OnPaint. This function is called for every form change. (I don't know if this method is better than simply pulling a picturebox and setting the background? Will this direct painting method be affected by frequent onpaint calls ?)

Because the icon in the upper-left corner is covered by the background image, the icon and title are also painted in this method.

Code private void DrawBackground (Graphics g) {if (_ topLeft. backgroundBitmap = null) // confirm that the image has been read {return ;}# region draws the background ImageAttributes attribute = new ImageAttributes (); attribute. setWrapMode (WrapMode. tileFlipXY); _ topLeft. drawSelf (g, null); _ topMiddle. drawSelf (g, attribute); _ topRight. drawSelf (g, null); _ centerLeft. drawSelf (g, attribute); contentPanel. backgroundImage = _ centerMiddle. backgroundBit Map; // The middle background color is replaced by the content panel background _ centerRight. drawSelf (g, attribute); _ bottomLeft. drawSelf (g, null); _ bottomMiddle. drawSelf (g, attribute); _ bottomRight. drawSelf (g, null); attribute. dispose (); // release the resource # endregion # region draw the title and LOGO // draw the title if (! String. IsNullOrEmpty (Text) {g. DrawString (Text, Font, new SolidBrush (ForeColor), ShowIcon? New Point (_ titlePoint. X + 18, _ titlePoint. y): _ titlePoint);} // draw the icon if (ShowIcon) {g. drawIcon (Icon, new Rectangle (4, 4, 18, 18) ;}# endregion}

 

 

 

After the main method is completed, let's take a look at the several Attributes provided:

Here we want to mention the skinfolder attribute. As expected, the options of existing skins should be displayed and selected directly. But the problem is that I didn't find a way to read the directory where the program is located in design mode (Application in design mode. startupPath reads the vs directory), so we have to use this method to let the designer select the skin directory. During the design, the program reads the configuration information under this directory. during actual operation, the program automatically intercepts the skin name in the skinfolder attribute, and then reads the skin through application. startuppath.

Some details

1. By default, this form has been embedded with a set of skin (Spring color), so even if you do not have a skin folder, it can still be displayed, just a set of skin.

2. Usage: Reference QLFUI. DLL in the project, and change the inheritance class from Form class to QLFUI. Mainfrm in the class to be used.

3. Because the previous series already have a detailed implementation of the form, here I only focus on the skin replacement section. The details of form creation will not be repeated.

4. If you have good insights or questions, please feel free to discuss with me, mail qianlf2008@163.com

Source code download

Download

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.