Use VC ++ to achieve a shaped window.

zhaozj2021-02-08  290

Use VC to achieve a shaped window.

Dalian Railway College (116028) Li Wenhui

With Microsoft's huge scores that WINDOWS in operating systems, the Windows user interface is also increasingly become industry standards. The unified interface gives the majority of users to the application and use of application software. But in the same side of the same side a day, it will be boredom for a long time, and it will develop some "standard" interface that is "off the rebellion". It will bring you a fresh feeling.

The Standard Windows Application window is generally a light gray rectangular appearance with the title bar, so the "Aldom" dialog / window is mainly color and shape.

Change background color

The background color of the Change dialog (window) is the simplest way to change the appearance of the Windows application, and there are generally two methods based on Windows creation and management mechanism. One is to process the WM_CTLCOLOR message, first create the brush of the selected background color, then call setBkcolor () or setDialogbkcolor () to draw the background of the window or dialog box. When you need to redraw a window or a dialog (or dialogue), Windows sends a message WM_CTLCOLOR to the dialog, the application processes the WM_CTLCOLOR message and returns a brush handle for painting the background of dialogue. The other is a WM_ERASEBKGND message in response to Windows, and Windows sends a WM_ERASEBKGND message to the window to inform the window erase background, you can use VC ClassWizard to overload the default handler of this message to erase the background (actually use brush painting), And return TRUE to prevent Windows erase windows.

2. Change window profile

By using the new SDK function setWindowRGN (), the drawing and mouse message can be defined in a specified area of ​​the window, so it is actually to make the window becomes the specified irregular shape (region shape). "Region" is a powerful mechanism in Windows GDI. The area is a space on the device, which may be any shape, and the complex area can be combined by each small area. Windows's area creation functions include createRectrGN (), createPolyRGN (), createPolygonRGN (), createPolygonRGN (), CreatellIPTRGN (), and createllipticRGN (), then combined with CombinerGn (), you can get a complex shape area, get a complex shape window shape.

Through the above method, although the "shaped" window can be obtained, it feels monotonous, and the shape is not "Cool". Can you get a more cool "Alien" dialog / window? The answer is yes. The following describes how to create a "shaped" dialog / window using bitmaps and masks.

3. Create a shaped dialog window with bitmaps

Creating a shaped dialog box with a bitmap is based on the color of the pixel to perform "button" processing, and all non-specified color pixel regions are combined. With this technology, it is actually a bitmap background for implementing dialog box / windows, and transparently processes the specified color area. The following is a case where the dialog box for the transparent bitmap is:

First, draw a picture of a plurality of Dialog box background with plot software, save the picture, save it with BMP, assume that it is Back.BMP. It should be noted that although the resource editor of the Visual C integrated development environment can only edit the bitmaps of no more than 16 colors, but we can store it in a true color method, don't pay attention to the Warning of Visual C .

The next step is to create a dialog-based application using Visual C AppWizard assumes named TRANS. Introducing a background image back.bmp with a resource editor, if it is high color, does not pay attention to warning information, click OK to confirm it. To explicitly, modify the default resource ID identifier IDB_bitmap1 is IDB_BackBMP. The STYLE for the dialog is then modified to Popup, Border is None, as shown in Figure 1. figure 1

Add zone processing function module void ctransdlg :: setupregion (CDC * PDC / * dialog window DC * /, uint backbitmapid / * background bitmap resource ID * /, UINT MASKBITMAPID / * area processing bitmap resource ID * / ColorRef transcolor = 0x00000000 / * transparent color value, default is black * /). So far, we temporarily think Maskbitmapid is equivalent to Backbitmapid. Its core work is a regional combination based on the MaskbitmapID indicates the pixel color of the bitmap. The complete code is as follows:

Void CTransdlg :: Setupregion (CDC * PDC / * dialog window DC * /,

Uint backbitmapid / * background bitmap resource ID * /,

UINT MASKBITMAPID / * Region processing bitmap resource ID * /,

ColorRef Transcolor / * Transparent color value * /)

{CDC MEMDC; CBITMAP CBITMAP; CBITMAP * PoldMEMBMP = NULL; ColorRef Cl; CRECT CRECT; UINT X, Y; CRGN WNDRGN, RGNTEMP;

/ / Get the window size

GetWindowRect (& CRECT);

// background bitmap resource ID

m_backbitmapid = backbitmapid

// Load bitmap

CBitMap.LoadBitmap (Maskbitmapid); MEMDC.CREATECOMPALEDC (PDC); Poldmembmp = MEMDC.SELECTOBJECT (& CBITMAP);

// First create the default full area as a complete window area

WNDRGN.CREATERECTRGN (0, 0, CRECT.WIDTH (), CRECT.HEIGHT ());

// The following two-layer loop is to check the background bitmap pixel color, perform a transparent area;

// When the pixel color is the specified transparent value, it will be cut off from the area.

// The number of member variables used in it m_maskleftoff, m_masktopoff,

// m_maskrightoff, m_maskbottomoff, m_framewidth

// and m_captionheight, which will be described later, which can be processed as 0.

For (x = m_framewidth m_maskleftoff;

X <= CRECT.WIDTH () - m_framewidth-m_maskrightoff; x ) {

For (y = m_captionHeight m_masktopoff; y <= crect.Height () - m_framewidth-m_maskbottomoff; y ) {

/ / Get the color value of the pixel of the coordinate

CL = MEMDC.GETPIXEL (X - m_framewidth-m_maskleftoff,

Y - m_captionHeight-m_masktopoff;

IF (col == transcolor) {

// The pixel color is the specified transparent color, creates a transparent "micro-region"

RGNTemp.createRectrGN (x, y, x 1, y 1); // "Dress", "deduct" transparent "micro-region" from a complete area

WNDRGN.COMBINERGN (& WNDRGN, & RGNTEMP, RGN_XOR);

/ / Delete the transparent "micro-region" that has just been created, release system resources

RGNTemp.deleteObject ();}}} if (Poldmembmp) MEMDC.SELECTOBJECT (POLDMEMBMP);

// Use the setting window as the specified area

SetwindowRgn ((hrgn) wndrgn, true);}

Reset the system default background erase operation, add a WM_ERASEBKGND message processing process, which can be simplified by using ClassWizard.

BOOL CTransDlg :: OnEraseBkgnd (CDC * pDC) {// TODO: Add your message handler code here and / or call default CRect rect; CDC memDC; CBitmap cBitmap; CBitmap * pOldMemBmp = NULL; GetWindowRect (& rect);

// Load background bitmap

CBitMap.LoadBitmap (M_BackBitmapid);

MEMDC.CREATECOMPALEDC (PDC); Poldmembmp = MEMDC.SELECTOBJECT (& CBITMAP);

// Copy the background bitmap to the window customer area

PDC-> Bitblt (0, 0, Rect.width (), Rect.Height (),

& MEMDC, 0, 0, SRCCOPY;

IF (Poldmembmp) MEMDC.SELECTOBJECT (POLDMEMBMP);

/ / Delete the system but the one-alsebkgn function

// Return CDialog :: OneRaseBkGnd (PDC);

Return True;}

Next is to add code to the message processing function onpaint () of WM_Paint. Since the background bitmap is relatively large, the regional processing is time consuming, the processing is only processed at startup. One method is onInitDialog () processing, but this will have a considerable delay from the startup program to the window, which is easy to cause the program that has not yet started. Yet another method is on OnPaint (), but in order to avoid repeated processing, you can add a judgment flag. The following is the code of onpaint (), the physical is generated by AppWizard, and the bold adds content for yourself.

Void cTransdlg :: onpaint () {= (isiconic ()) {

......

}

Else

{

IF (m_nfirstrun) {// First run flag // Modify the mouse cursor as waiting method becomwaitcursor (); // Set background area setupregion (getWindowDC (), IDB_BackBMP, IDB_BACKBMP, 0x00FFFFFFFFFFFFFFFFFFFFFFFf / * White * /); // Restore mouse cursor For normal mode endwaitcursor (); m_nfirstrun = 0;}

CDIALOG :: onpaint ();

}

The rest of the job is to set the size and location of the dialog window based on the size of the background bitmap, which can be implemented by calling MoveWindow () in OnInitDialog (). Add some variables and initialization, you can compile. Figure 2 is an example of a run a result:

figure 2

4. Further discussion

A single mode's shaped dialog is implemented, but in some cases require different styles, such as the title bar, border, etc., or only partially processing, this is the front two member variables m_framewidth and m_captionheight effect, by OnInitDialog () Judgment window style, make M_FraMewidth and M_CAPTIONHEIGHT different values. This part of the code is: BOOL CTRANSBMPDLG :: OnItDialog () {

......

// Todo: Add Extra Initialization Here

m_nfirstrun = 1; // Data setting, window left upper corner coordinate: m_left = 0, m_top = 0 // Background bit map wide: m_width = 535, m_height = 105 setsize (0, 0, 535, 105); // plate processing window border region from m_MaskLeftOff = m_MaskTopOff = m_MaskRightOff = m_MaskBottomOff = 0; // the window title bar and border pixel value m_FrameWidth = m_CaptionHeight = 0; // window style made LONG style = :: GetWindowLong (this-> m_hWnd , GWL_Style); // If the window style style is retained, different m_framewidth and m_captionheight values ​​are selected according to different window border types, / / ​​can also be paid according to the needs of the processing location ((STYLE & WS_BORDER) == WS_BORDER) m_FrameWidth = :: GetSystemMetrics (SM_CXBORDER); if ((style & WS_THICKFRAME) == WS_THICKFRAME) m_FrameWidth = :: GetSystemMetrics (SM_CXFIXEDFRAME); if ((style & DS_MODALFRAME) == DS_MODALFRAME) m_FrameWidth = :: GetSystemMetrics (SM_CXFIXEDFRAME) ; if ((style & WS_CAPTION) == WS_CAPTION) {m_FrameWidth = :: GetSystemMetrics (SM_CXFIXEDFRAME); m_CaptionHeight = :: GetSystemMetrics (SM_CYSMCAPTION);} m_CaptionHeight = m_FrameWidth * 2; // reset window position and size of the MoveWindow ( M_LEFT, M_TOP, M_WIDTH M_FRAMEWIDTH * 2, M_HEIGHT M_CAPTIONHEIGHT, TRUE;

......

Return True; // Return True UnsS you set the focus to a control

}

In addition, in order to further increase flexibility, the window style is not only controlled by background bitmap colors. By specifying the MaskbitmapId we call "Mongk" (multi-color), MaskbitmapId (Multi-color can also be, but generally there is no need). Figure 4 is an effect of implementing the mask bitmap of Figure 3, and increasing the border and title bar properties of the dialog form on the same background bitmap.

image 3

Figure 4

With this mask technology, you can create an arbitrary shape window, and it is independent of background bitmap. It should be noted that the controls in the dialog box, such as buttons, etc. Conveniently controlled. It is important to point out that the area specified by SetWindowRGN () is for the entire window, and the output area of ​​Bitblt () / stretchBLT () is for the client area, both are different, and the programming should be noted And flexible applications, this is why the previous variable is set.

5. Conclude

The creation of this shaped window is not only adapting to the dialog, but also adapts to all CWND-based derived windows. With this method, you can create any form you can draw, you can make the goal as long as you can draw it.

This document is proclaimed in Visual C 5.0, 6.0, running is normal, the operating system is Windows98SE.

references:

Microsoft, MSDN Library Visual Studio 6.0 RELEASE, 1998

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

New Post(0)