Step-by-Step imitation QQ interface (2): three-state simulation of texture buttons

Source: Internet
Author: User

The demo requires the ringsdk library. For compilation problems, see the original link in this article: Compile. The so-called three states are the normal status of the button, the highlighted status of the mouse move, and the pressed status. There should actually be a disable state, but this program has no unavailable buttons, so this effect will not be achieved. Because it is a texture rather than an actual button, you must process the mouse message and draw the three statuses by yourself. First of all, there must be a mouse position detection function hittest to check the button on which the mouse is located. Because the non-customer area of the program is only a rectangle frame with a size of 2, the title bar is simulated in the customer zone. Therefore, the hittest function calls and judges in the wm_mousemove message. It is nothing more than ptinrect to detect the coordinates of each button, therefore, the implementation of the hittest function will not be explained here, and the code will be clear. If the cursor is in the button area, this function returns the button ID. In the system button area, htminbutton, htmaxbutton, and htclose are returned, which is convenient for sending system commands directly. If there are no buttons, htcaption is returned, you can drag a window.

If hittest returns the button ID and the user does not press the mouse, the highlighted status of the button should be drawn. There is a problem here. After the painting is complete, the user continues to move the mouse, but the button is not removed, the wm_mousemove message will detect the need to draw a highlighted State, so that the mouse will flash when the painting is ongoing, therefore, you need to define a m_ncurwhere member variable to record the hittest detection value of the previous mouse:

C/C ++ code
   Int nwhere = hittest (...); If (nwhere! = M_ncurwhere) {// You need to draw a button to highlight or restore the original state if (nwhere! = Htcaption) checkanddrawbuttons (nwhere, 4); // draws the nwhere button's highlighted state else checkanddrawbuttons (m_ncurwhere, 0); // restores the original state of the highlighted button} m_ncurwhere = nwhere;

This ensures various state changes and only needs to be drawn once.

The implementation button is in the pressed status and needs to be processed in the wm_lbuttondown message. The first step is to perform the hittest detection. Here we also need to define a member variable m_ncursyscmd to mark which button is being pressed, then draw the button press status. Because you may have pressed the button and do not release the mouse to move it, you also need to define a member variable m_bincapture. In the wm_lbuttondown message, set this variable to true and setcapture to capture the mouse, in the wm_lbuttonup message, release the mouse and set this variable to false. In this way, the button painting function called in wm_mousemove can be used to determine whether the painting is in the pressed or highlighted State based on m_bincapture. The wm_lbuttonup message can also be used to determine whether to execute the button action based on this flag. Otherwise, you can press the mouse key elsewhere and move the mouse to a button to release the mouse. The button execution function is a little incorrect, you should determine that m_bincapture is true and m_ncursyscmd is equal to the button detected by hittest before executing the button function. When the mouse key is pressed, only the button marked by m_ncursyscmd is drawn in the pressed and normal status. It is found that qq2009 is not implemented in this regard. After the button is pressed, the mouse button is not released and the button status does not change.

According to this mechanism, the judgment in wm_mousemove should be modified, and the judgment on the button pressing status should be added:

C/C ++ code
   Ringmainmsg (wm_mousemove) {int nwhere = hittest (PARAM); If (m_bincapture) {// move if (m_ncursyscmd = nwhere & m_ncurwhere! = Nwhere) {// move the mouse out of the button and draw the checkanddrawbuttons (nwhere, 8);} else if (m_ncursyscmd! = Nwhere & m_ncursyscmd = m_ncurwhere) {// draw the normal status checkanddrawbuttons (m_ncursyscmd, 0);} m_ncurwhere = nwhere; return 0;} else {lresult res; if (nwhere! = M_ncurwhere) {// You need to draw a button to highlight or restore the original state if (nwhere! = Htcaption) checkanddrawbuttons (nwhere, 4); // The highlighted else checkanddrawbuttons (m_ncurwhere, 0); // restore the original state} res = defaultproc (PARAM); m_ncurwhere = nwhere; return res ;}}

Now, the mouse detection function for the button has been completed, and the rest is the button painting. There are three buttons to draw: The system button, a menu button that can pop up next to the user's profile picture, and a personalized signature button ([I am online] is also a button, however, this is the same as the personalized signature button implementation, which saves time and does not work.) and the row of buttons on the toolbar below the user's profile picture. The system button is drawn using the most common method. Here, you can paste the system button resource image to the desired state, you only need to draw the corresponding area on the image to the target.

However, there is still a skill here. The bottom row is the normal button, which is transparent for the UI color requirements in the future. Only borders and lines are not transparent, in this way, you need to restore the background color when creating the normal button, and then draw the normal button transparently, which is a bit of trouble. Therefore, a memory image of the system button area is initialized during program initialization, in the wm_paint message, the image in the normal system button area is drawn to the memory image by the way, so that the system button state can be restored as long as the memory image is drawn again.

Next, draw the buttons in the toolbar to see the required resource images. There are two images in total:


The three-state button effect is implemented, the second is the highlighted state, and the third is the pressed state:

Well? How is this implemented? The key lies in 2nd resource images, which are divided into two parts: the highlighted state on the left and the pressed state on the right. Each part of the image is 5 pixels wide, the left and right sides of each two pixels are the left and right sides of the button border, the middle 1 pixel is the middle of the button pattern, you need to horizontally stretch to the button to remove the width of the left and right sides of the border. First, restore the background pattern, then draw the highlighted button, and finally draw the entire toolbar image transparently without affecting the created background. The drawing of the pressed state is slightly different, because the image of the pressed Button needs to be shifted to one pixel in the lower right corner, and the button is pressed, so that the entire toolbar image cannot be painted, you need to draw the pressed Button image, and then draw the button on the left and right sides of the button.

The button next to the user's profile picture is similar to the toolbar, so I won't explain it. I can see the source code. The Source Region coordinates of the image in the Code are a little round, you need to be clear-minded to avoid confusion. You need to understand the parameter definitions of the drawto and stretchto functions of the image library. For details, refer to the ringsdk help file.

By the way, the image database's dual-buffer rendering operation is a direct operation of image data. To put it bluntly, only some colorref array data is moved. In addition to drawing text, HDC is not required, therefore, the speed and efficiency are very high.

At this point, the three-state simulation of the texture button is complete, and other functions need to be implemented. The tooltip adds the tooltip of the toolbar button, however, the two buttons on the rightmost side, "Open the message box" and "change the appearance", require additional processing. Because the window size can be adjusted, the original coordinates of the size change are incorrect, so we need to dynamically change the coordinates. Where can we change the wm_size message? When you change the window size, you cannot move the mouse over the two buttons, and wm_size messages are too frequent, we only need to update the coordinates after the size adjustment. The message is wm_exitsizemove:

C/C ++ code
   Toolinfo Ti; copyrect (& ti. rect, & rc); // RC indicates the updated coordinate m_tip-> settoolinfo (& Ti );

The code in the actual program must be more complex. The tooltip of the system button is not added. If you are interested, you can do it yourself. You need to update coordinates like the buttons in the two toolbar.

In addition, click the button next to the user's profile picture to bring up the menu. The last two items of the menu in qq2009 are different from those in the system bar icon, so it is no longer troublesome, the system bar icon is displayed.

The personalized signature button will display an editing box that allows you to edit the signature. this is not difficult. The trouble is that this editing box needs to be automatically hidden. Processing the en_killfocus message cannot fully implement the effect, because there are no other controls on the interface to grab its focus, only the program loses focus will have this message, so you need to add a judgment in wm_lbuttondown. Since the message wm_lbuttondown is received, it indicates that you have clicked the mouse outside the editing box to hide it. Unfortunately, this is not enough. When you adjust the window size, you click the non-customer zone and there is no wm_lbuttondown message. Therefore, you need to add a judgment in the wm_entersizemove message, in this way, the personalized signature editing function is complete.

At this point, this program has implemented three-state simulation of all buttons, functional response of system buttons, tooltip of toolbar buttons, editable personalized signatures, and a menu can be displayed. The extended type of ws_ex_toolwindow is added, and the program will not appear on the taskbar. The function of executing the program only once is not limited. There is a small bug. Move the mouse to the system button area and the system button is highlighted. Then, move the mouse up and out of the window quickly. The button status will not be restored because the wm_mousemove message is absent, to solve this problem, You Need To trackmouseevent and restore the button status in the wm_mouseleave message. If you are interested, you can solve it yourself.

Finally, let's look at the program:

The toolbar at the bottom of the interface will be implemented in different ways later. The next article will explain how to implement an exciting Function: interface color. Open the program resources and you can see that the Settings dialog box for changing the appearance already exists. Later, we will explain how to customize the control and implement the QQ change appearance dialog box.

Demo: http://download.csdn.net/source/1982937

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.