|
|

楼主 |
发表于 2005-2-27 23:26:00
|
显示全部楼层
附:[转帖]在全屏(资源独占)游戏中弹出非模态对话框的
[转帖]在全屏(资源独占)游戏中弹出非模态对话框的
DirectDraw 7.0
Displaying a Window in Full-Screen Mode
[Visual Basic]
The information in this topic pertains only to applications written in C++.
[C++]
In full-screen mode, DirectDraw has exclusive control over the display. As a result, dialog boxes and other windows created through GDI are not normally visible. However, by using special techniques you can incorporate a Windows dialog box, HTML Help, or any other kind of window in your application.
The FSWindow Sample illustrates how a dialog box can be displayed and updated in a full-screen application, and how mouse clicks and keystrokes work just as if the dialog box were being displayed by GDI.
In FSWindow, the dialog box is created and "shown" as an ordinary dialog window:
hWndDlg = CreateDialog(g_hInstance,
MAKEINTRESOURCE(IDD_DIALOG_SAMPLE),
hWnd, (DLGPROC) SampleDlgProc);
ShowWindow(hWndDlg, SW_SHOWNORMAL);
Of course, at this point the dialog box is shown only on the hidden GDI surface. It does not appear on the primary surface, which is controlled by DirectDraw.
If the hardware capabilities include DDCAPS2_CANRENDERWINDOWED (see DDCAPS), displaying and updating the dialog box is easy. The application simply calls the IDirectDraw7::FlipToGDISurface method, which makes the GDI surface the primary surface. From now on, all updates to the dialog box will be displayed automatically, because GDI is now rendering directly to the front buffer. The application continues rendering to the back buffer, and on each pass through the rendering loop the contents of the back buffer are blitted to the front buffer by DirectDraw. The dialog box is not overwritten because the front buffer is clipped to the application window, and the dialog box is obscuring part of that window.
The following code, from the FSWindow_Init function, creates the clipper, associates it with the application window, and brings the GDI surface to the front:
if (ddObject->CreateClipper(0, &ddClipper, NULL) == DD_OK)
ddClipper->SetHWnd(0, hwndAppWindow);
ddObject->FlipToGDISurface();
Then, in the FSWindow_Update function, the following code blits the rendered contents of the back buffer to the clipping region:
ddFrontBuffer->SetClipper(ddClipper);
ddFrontBuffer->Blt(NULL, ddBackBuffer, NULL, DDBLT_WAIT, NULL);
Note that because the GDI surface is the primary surface, Windows continues displaying the mouse cursor. (This would not be the case, however, if the application were using DirectInput with the mouse device at the exclusive cooperative level.)
For hardware that does not have the DDCAPS2_CANRENDERWINDOWED capability, the process of displaying and updating a window in full-screen mode is somewhat more complicated. In this case, the application is responsible for obtaining the image of the window created by GDI and blitting it to the back buffer after the full-screen rendering has been done. The entire back buffer is then flipped to the front in the usual way.
The FSWindow sample provides two different methods for accessing the display memory of the window, depending on whether the content is static or dynamic. The method for static content is faster because it involves blitting from a memory device context rather than a screen device context. This method should be used for windows that do not change, such as informational dialog boxes. (Remember, though, that unless you manually update the bitmap in response to events, even basic animation such as a button press will not be visible to the user.)
If the content is static, FSWindow calls the CreateBMPFromWindow function when the window is initialized. This function creates a bitmap and blits the contents of the window into it. The bitmap handle is stored in the global variable hwndFSWindowBMP. Whenever the primary surface is about to be updated, this bitmap is blitted to the back buffer, as follows:
if (FSWindow_IsStatic)
{
hdcMemory = CreateCompatibleDC(NULL);
SelectObject(hdcMemory, hwndFSWindowBMP);
BitBlt(hdcBackBuffer, x, y, cx, cy, hdcMemory, 0, 0, SRCCOPY);
DeleteDC(hdcMemory);
}
If, on the other hand, the content of the window is dynamic, the following code is executed. It blits the image directly from the GDI surface (represented by the hdcScreen device context) to the back buffer.
BitBlt(hdcBackBuffer, x, y, cx, cy, hdcScreen, x, y, SRCCOPY);
The coordinates represent the position and dimensions of the window on the GDI surface, as retrieved through a call to GetWindowRect.
When the FSWindow application is running on hardware that does not have the DDCAPS2_CANRENDERWINDOWED capability, it does not use the GDI surface, so Windows cannot display the mouse cursor. The application takes over this task by obtaining information about the cursor and displaying it on the back buffer just before the flip.
首先,本文的方法只适合用C++写的程序
在全屏模式,由于DirectDraw太公孙,因此只有采用特殊技巧,才能显示对话框,html帮助,etc
下面就是说用FSWindow创建对话框。
一般来说,是:
hWndDlg = CreateDialog(g_hInstance,
MAKEINTRESOURCE(IDD_DIALOG_SAMPLE),
hWnd, (DLGPROC) SampleDlgProc);
ShowWindow(hWndDlg, SW_SHOWNORMAL);
当然这只是在默认是GDI的时候才可以,有时候就不行,比如现在。
如果硬件支持DDCAPS2_CANRENDERWINDOWED,那么就比较好说。应用程序首先调用IDirectDraw7::FlipToGDISurface ,让GDI
接口获得控制权。。。。。。。。。。。(此处省略250字)
下面这个代码,来自FSWindow_Init函数,创建clipper,关联应用程序窗口,并且把GDI升权:
if (ddObject->CreateClipper(0, &ddClipper, NULL) == DD_OK)
ddClipper->SetHWnd(0, hwndAppWindow);
ddObject->FlipToGDISurface();
然后下面这段参考自FSWindow_Update的代码负责维护:
ddFrontBuffer->SetClipper(ddClipper);
ddFrontBuffer->Blt(NULL, ddBackBuffer, NULL, DDBLT_WAIT, NULL);
由于GDI获得权限,因此这种情况下鼠标显示很正常。
如果硬件不支持DDCAPS2_CANRENDERWINDOWED ,那么应用程序需要先接受GDI画好的图片,然后。。。。。。。。。(省略200
字)
FSWindow提供2种方法,这2种方法分别适用于静态content和动态content。静态content比较快,因为内存设备环境比窗口设
备环境快。当然局限就是只能画不变化的对话框,比如一些提示了,请记住采用这种方法必须自己改变图片,如果打算有一些
好看的操作。(估计你要的就是这种。。)
对于静态的,在初始化窗口的时候,FSWindow 调用CreateBMPFromWindow ,该函数创建位图句柄并在窗口上显示,保存位图
句柄的hwndFSWindowBMP是全局变量。如下:
if (FSWindow_IsStatic)
{
hdcMemory = CreateCompatibleDC(NULL);
SelectObject(hdcMemory, hwndFSWindowBMP);
BitBlt(hdcBackBuffer, x, y, cx, cy, hdcMemory, 0, 0, SRCCOPY);
DeleteDC(hdcMemory);
}
对于动态的,用下面的函数:
BitBlt(hdcBackBuffer, x, y, cx, cy, hdcScreen, x, y, SRCCOPY);
该函数的参数来自GetWindowRect()
如果硬件不支持DDCAPS2_CANRENDERWINDOWED 的时候,画鼠标需要自己画:displaying it on the back buffer just before
the flip
|
|