Establish a magnetic form

xiaoxiao2021-03-06  20

Some famous sharing software not only have excellent function, but also in the design techniques of the program interface, WinAmp is one of the representatives. WinAMP has two extraordinary, one is to replace the appearance of the form, which is now commonly known as "skin"; the other is magnetic form tips. Magnetic forms are close to each other when the form is close to a certain distance, or each other, then when dragging the main form, other forms sticking together, it seems to change It became a form. Domestic MP3 player rookie CDOK also implements this technique, and more, after sticking together, the form does not have a master from the point, dragging any of the forms together will cause other forms. mobile. There are a lot of posts on how to design magnetic forms on 9CBS, indicating that this skill is deeply favored by the majority of programmers. This article first adds a few netizens's methods to analyze, and then give me a more feasible implementation method and source code. Implementing the magnetic form is basically divided into two steps. The first step is to implement the paste operation between the forms between the two forms is within a certain distance, the second step is to move the form while moving the form. Other forms together.

The difficulty of implementing the form of the form is difficult to achieve this operation. It is assumed that there are two forms Form1 and Form2, and the mobile FORM2 is approached to Form1, and when FORM2 is less than the nearest distance of Form1 is smaller than the Distance. Obviously, it should be judged during mobile form2, what is the program in inserting a judgment code in what location? Some people on 9CBS believe that the timer can be used, and the position of each form is checked every other time. This approach has obvious disadvantages, not to say that the timer should be waste system resources, and its instantity is difficult to guarantee. If the timing value is shortened, the waste of CPU resources is more, so I don't have much to say. Reasonable way is to use the news generated by the system, but what news is taken? The form generates WM_WINDOWPOSCHANGING and WM_MOVING messages when moving, and WM_WINDOWPOSCHANGED and WM_MOVE messages are generated after the end. LParam WM_WINDOWPOSCHANGING WM_WINDOWPOSCHANGED message parameters and a pointer to the structure WINDOWPOS, WINDOWPOS defined as follows: typedef struct _WINDOWPOS {HWND hwnd; // Ping sentence window HWND hwndInsertAfter; Z // window sequence int x; x-coordinate window // int y; / / Window Y coordinate int CX; // The width INT CY; // window is highly uint flags; // flag, according to the position of the window} WindowPos; It can be seen that the wm_windowposchanged message is not only in the window. Generation when it is generated during its Z order, including the display and hidden of the window. So I think this news is not the best choice. The parameter lparam of WM_MOVING and WM_MOVE messages is a RECT structure pointer, which is simpler than the WM_WINDOWPOSCHANGED message, and I use this message. Below I give an example program written by C Builder. In order to facilitate the reading of the program, first define an enumeration data type, indicating the adhesive state of the form. At the same time, a class is defined, encapsulating the form paste-related data, where the enable is to prevent repetition operations, the method is to set the enabled whether the enable is invoked, and the operation is checked before operation. No, otherwise it will return directly.

Figure 2 Paste Sample Example (Lack) // Forms of Forms // Forms Class, in order to simplify, PUBLIC declaration class cformattachstyle {public: bool enabled; / / prevent repeated paste related operations HWnd attachto; // is pasted in which window int xstyle; // The stick state in the left and right direction int yStyle; // Paste state in the vertical direction int XPOS; // Pasted X coordinate int ypos; // Paste the Y coordinate cFormattachStyle () // Initialization data {xStyle = as_none; yStyle = as_none; enabled = true; hattachto = NULL;}}; function distancein is used to determine if the distance between the two integers is within the specified range: // The absolute value of the difference between integer I1 and I2 is less than I3 Bool Distancein (unsigned int I1, unsigned Int I2, unsigned Int i3) {IF (I1> I2) {// Make sure I2> = I1; INT T = I1; I1 = I2; I2 = T;} RETURN I2-I1 <= I3;} // --------- -------------------------------------------------- ---------------- // i1 <= I2 BOOL MID (unsigned int I1, unsigned int I2, unsigned int 3) {return ((i1 <= i2) && (i2 } // ----------------------------------------------------------------------------------------------------------------------------------------------------- -------------------------- AttachToform is a key function for processing the form paste, if pasted, save the pasted form The handle and adjust the location of the form. The TAG property of the form is used in the function saves an instance pointer of a CFormattachStyle class, which will be described later, the parameter distance represents the distance of the paste. The window is pasted up and down, and there are three forms in the left and right, and it needs to be judged.

// Stick the form MY to the main form Bool AttachToform (TForm * MY, TFORM * FORM, RECT * R, INT DISTANCE) {cFormattachStyle * MyStyle = (cFormattachStyle *) My-> tag; if (MyStyle == Null RETURN FALSE; // This form does not support paste // position of the form of the form, the location of the form, the location Rect RMain; getWindowRect (Form-> Handle, & RMAIN); MyStyle-> attachto = null; myStyle-> ypos = r-> Top; MyStyle-> xpos = r-> LEFT; // Direction judgment MyStyle-> YStyle = as_none; if (MID (RMain.right, R-> Left, RMain.right) || MID (r-> Left, RMain.LEFT, R-> Right || (MyStyle-> xStyle! = as_none)) {if (r-> Top, rmain.bottom, space) {mysty-> yStyle = as_bottom; MyStyle-> YPOS = rMain.bottom;} else IF (r-> top, rmain.top, space) {mysty-> yStyle = as_top; myStyle-> YPOS = RMain.top;} else if (distancein (r-> bottom) , rmain.top, space) {mysty-> yStyle = as_t_top; myStyle-> YPOS = RMain.top- (r-> bottom-r-> TOP);}} // 向 向MyStyle-> xStyle = as_none; if (MID (RMain.top, R-> Top, RMain.Bottom) || MID (r-> Top, RMain.top, R-> Bottom) || (MyStyle-> YStyle! = As_none)) {if (r-> left, rmain.left, space) {mysty-> xstyle = as_left; myStyle-> xpos = rmain.Left;} else if (distancein (r-> left, rmain .right, space) {mysty-> xstyle = as_right; myStyle-> xpos = rmain.right;} else if (distance ") {mysty-> xStyle = as_l_left;

MyStyle-> XPOS = RMain.Left- (r-> right-r-> left);}} my-> left = myStyle-> xpos; my-> top = myStyle-> YPOS; if (MyStyle-> xstyle! = As_none || myStyle-> YStyle! = As_none) {// Paste Success MyStyle-> attachto = form-> handle;} return bool (MyStyle-> attachto);} DO_WM_MOVING Handling WM_MOVING in message looping, parameters MY is a form of processing messages, and the MSG is the message parameter. // event processing WM_MOVING void Do_WM_MOVING (TForm * My, TMessage & Msg) {CFormAttachStyle * MyStyle = (CFormAttachStyle *) My-> Tag; if (MyStyle && MyStyle-> Enabled) {MyStyle-> Enabled = false; // prevent duplicate Operation RECT * R = (Rect *) msg.lparam; // Process paste, only to the paste to the main form for judgment TFORM * formApplication-> mainform; attachtoform (MY, R, 12); // Check if it can be pasted Form MyStyle-> enabled = true; // Restore operation status} msg.result = 0; // Notification system, message has been processed}

Realization of the associated movement of the form is smaller than the process of processing form paste. But from the post on 9CBS, the method used is monotonous and not good, I don't recommend it. A more intuitive way is to use the form of MouseDown, MouseMove, and Mouseup events, first define whether a flag mouse is pressed: BOOL BMOUSEDOWN; Setting in the mousedown event: bmousedown = true; set in the Mouseup event: bmousedown = false; Be processed in the MouseMove event: if (bmousedown) {// mobile current form ... // calculate the displacement INT DX; int Dy; // calculates DX and DY ... // Mobile Other paste to The most obvious problem of the current form ...} This method is two: 1. When the mouse is pressed on the control, the MouseDown and MouseUp events cannot be received, if each control is monitored The incident is quite large. 2, the mouse event in the window title bar is difficult to handle properly. In fact, similar to the previous paragraph, the WM_MOVING event for processing the form is a better way. That is, moves other forms in the WM_MOVING event. There are many ways to move other forms. Some people use the sending message. Specific as follows: // DX and DY are the current form mobile distance // hmove is the form to move // ​​WM_MOVEFORM is a custom message PostMessage (HMOVE, WM_MOVEFORM, DX, DY); When the mobile form processes the WM_MOVEFORM message, move yourself to the new location. If it is a language of VB, Delphi, you can set it directly to the LEFT and TOP properties. The method I use is to use the API function setWindowPOS, which re-sets the location of the specified window.

My reference code is as follows: // Move the other form of other forms of moving together VoID UnionOtherform (TForm * My, TFORM * FORM, INT DX, INT DY) RETURN; CFORMATTACHSTYLE * MyStyle = (CFormattachStyle * (Form-> tag); if (MyStyle) {if (MyStyle-> Enabled && myStyle-> attachto == mystyle-> attachto == mystyle-> enabled = false; int x1 = form-> left; int y1 = form- > Top; setwindowpos (form-> handle, my-> handle, x1 dx, y1 dy, form-> width, form-> height, swp_nosize | swp_noactivate); MyStyle-> enabled = true;}}} // Mobile pasted together other form void AdjuctFormpos (TForm * my, Rect * r) {// Adjust window position int DY = r-> Top-my-> top; int dx = r-> Left-my-> Left; my-> top = r-> Top; my-> left = r-> left; // check the created form for one by one (int i = 0; iformcount; i ) {tform * form = screen-> Forms [I]; if (form! = my) {// Adjust the attached window location unionotherform (MY, FORM, DX, DY);}}} // Handling WM_MOVE event Void do_wm_move (TForm * My, TME SSAGE & MSG) {// Processing the position of the paste CFORMATTachStyle * MyStyle = (cformattachstyle *) My-> tag; if (MyStyle && myStyle-> enabled) {if (MyStyle-> Enabled && myStyle-> attachto) {/ / Paste Success MY-> LEFT = MyStyle-> xpos; my-> TOP = MyStyle-> Ypos;}} msg.result = 0; // Notification system, message has been processed} There is a C Builder programming skill, That is to use the Screen global object. If the initialization of the Paste function is required to use the Paste function, the pointer to the form is assigned to the TAG form of the form, then other operations can be omitted in addition to the WM_MOVING and WM_MOVE events that processes it.

转载请注明原文地址:https://www.9cbs.com/read-43704.html

New Post(0)