Implementation of the DirectDraw painting function

Source: Internet
Author: User

1. Problem Source

We developed an ActiveX playback control using DirectDraw. The customer needs to achieve the picture-in-picture effect during the application, which only needs to overlay one or two widgets, however, the problem is that the two windows will cause sharp flashes, because the two windows will refresh the same area constantly. What should I do?

2. Initial Plan

I first came up with DirectDraw cropping. Cropping refers to the restriction on the output area of the image. Therefore, I guess you only need to restrict the cropping area of the large image and remove the area of the small image from the large image to avoid blinking.

DirectDraw surface trimming is implemented through the idirectdrawclipper interface. In normal window mode, the sethwnd method is called to associate the cropping tool with a window. DirectDraw automatically limits the display area of the image to the window. The setcliplist function is used to create any cropping tool with any shape. Its prototype is as follows:

Hresult setcliplist (
Lprgndata lpcliplist,
DWORD dwflags
);

The parameter "lpcliplist" is used to specify the cropping area. The second parameter "dwflags" is not used currently. Set this parameter to 0.

If we are familiar with Windows GDI functions, we will not be unfamiliar with the rgndata structure. It is used to describe the rectangle of a region. The specific structure of rgndata is as follows:

Typedef struct _ rgndata {
Rgndataheader RDH; // header, used to describe the main information of Region
Char buffer [1]; // placeholder, starting from buffer, which is the data of all rectangles that make up region.
} Rgndata, * prgndata;

The structure of rgndata is as follows:

------------------
| Rgndataheader | <-RDH
------------------
| Rect 1 | <-Buffer
------------------
| ...... |
------------------
| Rect n |
------------------

The structure of rgndataheader is:

Typedef struct _ rgndataheader {
DWORD dwsize; // the size of the current structure, which is equal to sizeof (rgndataheader)
DWORD itype; // rdh_rectangles
DWORD ncount; // Number of rectangles that constitute Region
DWORD nrgnsize; // region data size, equal to ncount * sizeof (rect)
Rect rcbound; // The boundary rectangle of all rectangles
} Rgndataheader, * prgndataheader;

Now let's take a look at the implementation of the painting function.

Window layout crop window
----------------------------------------------------
|
| Small image | crop rectangle 1 |
| Hwnd1 | RC1 |
| RC1 |
| ------------- | --> | ------------------------ |
|
| Large window |
| Hwnd0 | crop the rectangle 0 |
| RC0 | RC0 |
|
----------------------------------------------------

The left side is the window layout, and the right side is the corresponding cropping window. The cropping code is roughly as follows:

Idirectdrawclipper * pclipper = NULL; // defines the cropping device.
Pdirectdraw-> createmediper (0, & pclipper, null); // create a cropping device. pdirectdraw is the previously created idirectdraw interface.

 

Const int ncount = 2; // Number of rectangles
Rect RC [ncount]; // defined as an array.
: Getwindowrect (hwnd0, & rc [0]); // obtain the large window area
: Getwindowrect (hwnd1, & rc [1]); // obtain the small window area

Rgndata * prgn = (rgndata *) malloc (sizeof (rgndataheader) + ncount * sizeof (rect); // allocate space required by region
Prgn-> RDH. dwsize = sizeof (rgndataheader );
Prgn-> RDH. itype = rdh_rectangles;
Prgn-> RDH. ncount = ncount;
Prgn-> nrgnsize = ncount * sizeof (rect );
Prgn-> rcbound = RC [0]; // The large window here is the boundary rectangle.

// Set the cropping window
RC [0]. Top = RC [1]. bottom;
RC [1]. Left = RC [1]. Right;
RC [1]. Right = RC [0]. Right;
Memcpy (& prgn-> buffer [0], & rc [0], prgn-> nrgnsize );

Pclipper-> setcliplist (prgndata, 0 );
Pfrontsurface-> setclipper (pclipper );

// Note that prgn cannot be released during playback. If you want to release it, call pclipper-> setcliplist (null );

The above code did achieve my expected results, but another problem emerged: the playing screen is always displayed at the top of the screen, and even the playing program is minimized. Why is there no such problem with the cropping tool constructed by sethwnd? I decided to find out exactly.

Idirectdrawclipper provides a function to obtain the internal Cropping Area of the cutter. Its prototype is:

Hresult getcliplist (
Lprect,
Lprgndata lpcliplist,
Lpdword lpdwsize
);

I return to the sethwnd window cropping mode. I use the above function to obtain the cropping area and display the main information. I found that the cropping area will change dynamically! When the playing window is normally displayed, the cropping area is equal to the window area. When the playing window is blocked by other windows, the cropping area is changed to the unblocked part of the window. When the playing window is minimized, the number of rectangles In the cropping area changes to 0, that is, the cropping area changes to null.

Originally, a seemingly simple sethwnd function, Windows automatically did a lot of work for us, and once setcliplist is used, it indicates that we need to maintain the cropping area by ourselves (it is no wonder that sethwnd and setcliplist cannot be used at the same time). This is not an easy task (maybe I don't know how to implement it easily ).

3. select another solution

It seems that I have to build another path. I quickly thought of window pruning. setjavaswrgn is such a function, its prototype is:

Int setmediawrgn (
Hwnd, // handle to window
Hrgn, // handle to region, which can be created through API functions such as creatrectrgn or crgn class
Bool bredraw // window redraw Option
);

In fact, setmediawrgn is often used to create a special window. Soon I confirmed my thoughts. However, I am still not satisfied with this solution, because setting the cropping area is troublesome for users. Is there any better way?

4. Final Implementation

The answer is yes, that is, the cropping attribute of the window. Remember, one of the window properties is ws_clipsiblings. If a child window has this attribute, if it is overwritten by another child window, it will not update the content in the overlapping area during painting.

You can specify window properties when creating a window dynamically, or use the setwindowlong function:

Long setwindowlong (
Hwnd,
Int nindex,
Long dwnewlong
);

Usage:

DWORD dwstyle =: getwindowlong (hwnd, gwl_style );
Dwstyle | = ws_clipsiblings;
: Setwindowlong (hwnd, gwl_style, dwstyle );

Now everything is fine, but there is another question to consider. This is the question of who is at the top of the window overlap, that is, the Z-Order question. The default Z-order is related to the window creation sequence. If you want to specify it dynamically, You have to submit another API:

Bool setwindowpos (
Hwnd,
Hwnd hwndinsertafter,
Int X,
Int y,
Int CX,
Int cy,
Uint uflags
);

If we want to move a window to the top of all sub-windows, we can call it as follows:

: Setwindowpos (hwnd, hwnd_top, 0, 0, 0, 0, swp_nomove | swp_nosize );

For more information about the above APIs, see msdn.

5. Postscript

Finally, I summarized my task. Although it took less than a day to complete my work, I experienced several improvements in the previous and later stages. At first, I thought about implementing DirectDraw in the field of DirectDraw technology based on inertial thinking. With the exposure of problems in practical applications, I had to use other methods, then I thought of the most direct and simple implementation method.

This is also true for many projects. If we can analyze different solutions carefully before doing so, we can avoid a lot of detours and waste of human and material resources. Of course, the premise is that we need to be familiar with related technologies and think deeply about problems.

In addition, some may ask, why don't you use a control and use the overlay inside DirectDraw to implement the painting function? This is because in our application, each playing window is independent. The so-called picture-in-picture is only a layout of multiple playing windows. Therefore, one screen uses one control for greater flexibility.

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.