[問題] 使用Win32 API來建立雙視窗
想要利用Win32 API來建立兩個獨立的視窗,
這兩個視窗是可以分別控制,不一定要誰上誰下,且兩個視窗可以互相溝通
目前我拿範例程式來改,有問題(如下):
D3DFWSample.exe 中第一個可能發生的例外狀況: 0xC0000005: 寫入位置 0x00000010
時發生存取違規。
請高手幫忙,謝謝!!
或是有什麼資料可以讓我參考~
以下是程式碼
#include <windows.h>
#include "Renderer.h"
#include "Scene.h"
#define CLIENT_WIDTH 640
#define CLIENT_HEIGHT 480
#define WINDOW_NAME "D3DFWSample" // 視窗名稱
#define WINDOW_NAME2 "D3DFWSample2" // 視窗名稱2
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM
lParam);
LRESULT CALLBACK WindowProc2(HWND hWnd2, UINT msg2, WPARAM wParam2, LPARAM
lParam2);
//-------------------------------------------------------------
// 應用程式的進入點
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR
lpCmdLine, int nCmdShow)
{
char clsName[] = "D3DFWSampleClass"; // 視窗類別名稱
char clsName2[] = "D3DFWSampleClass2"; // 視窗類別名稱2
HWND hWnd;
MSG msg;
HWND hWnd2;
MSG msg2;
// 視窗類別初始化
WNDCLASSEX wcex = {
sizeof(WNDCLASSEX),
NULL,
WindowProc,
0,
0,
hInstance,
NULL,
LoadCursor(NULL, IDC_ARROW),
NULL, NULL,
clsName,
NULL
};
// 視窗類別初始化2
WNDCLASSEX wcex2 = {
sizeof(WNDCLASSEX),
NULL,
WindowProc2,
0,
0,
hInstance,
NULL,
LoadCursor(NULL, IDC_ARROW),
NULL, NULL,
clsName2,
NULL
};
// 視窗類別的登錄
if(RegisterClassEx(&wcex) == 0){
return 0; //登錄失敗
}
// 視窗類別的登錄2
if(RegisterClassEx(&wcex2) == 0){
return 0; //登錄失敗
}
// 產生視窗
if(isFullScreen) { // 全螢幕
int sw;
int sh;
// 取得畫面的寬與高
sw = GetSystemMetrics(SM_CXSCREEN);
sh = GetSystemMetrics(SM_CYSCREEN);
hWnd = CreateWindow(
clsName,
WINDOW_NAME,
WS_POPUP,
0,
0,
CLIENT_WIDTH,
CLIENT_HEIGHT,
NULL,
NULL,
hInstance,
NULL
);
}
else {
hWnd = CreateWindow(clsName,
WINDOW_NAME,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
// 重設視窗的大小
RECT rect;
int ww, wh;
int cw, ch;
GetClientRect(hWnd, &rect); // 取得用戶端部份大小
cw = rect.right - rect.left; // 計算用戶端區域以外的寬度
ch = rect.bottom - rect.top; // 計算用戶端區域以外的高度
GetWindowRect(hWnd, &rect); // 取得整體視窗的大小
ww = rect.right - rect.left; // 計算整體視窗的寬度
wh = rect.bottom - rect.top; // 計算整體視窗的高度
ww = ww - cw; // 用戶端區域以外所需要的寬度
wh = wh - ch; // 用戶端區域以外所需要的高度
// 再計算視窗的大小
ww = CLIENT_WIDTH + ww; // 必要的視窗寬度
wh = CLIENT_HEIGHT + wh; // 必要的視窗高度
// 再設定視窗的大小
SetWindowPos(hWnd, HWND_TOP, 0, 0, ww, wh, SWP_NOMOVE);
}
// 產生視窗2
if(isFullScreen) { // 全螢幕
int sw;
int sh;
// 取得畫面的寬與高
sw = GetSystemMetrics(SM_CXSCREEN);
sh = GetSystemMetrics(SM_CYSCREEN);
hWnd2 = CreateWindow(
clsName2,
WINDOW_NAME2,
WS_POPUP,
0,
0,
CLIENT_WIDTH,
CLIENT_HEIGHT,
NULL,
NULL,
hInstance,
NULL
);
}
else {
hWnd2 = CreateWindow(clsName2,
WINDOW_NAME2,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
// 重設視窗的大小
RECT rect;
int ww, wh;
int cw, ch;
GetClientRect(hWnd2, &rect); // 取得用戶端部份大小
cw = rect.right - rect.left; // 計算用戶端區域以外的寬度
ch = rect.bottom - rect.top; // 計算用戶端區域以外的高度
// 計算整個視窗的橫向寬度
GetWindowRect(hWnd2, &rect); // 取得整體視窗的大小
ww = rect.right - rect.left; // 計算整體視窗的寬度
wh = rect.bottom - rect.top; // 計算整體視窗的高度
ww = ww - cw; // 用戶端區域以外所需要的寬度
wh = wh - ch; // 用戶端區域以外所需要的高度
// 再計算視窗的大小
ww = CLIENT_WIDTH + ww; // 必要的視窗寬度
wh = CLIENT_HEIGHT + wh; // 必要的視窗高度
// 再設定視窗的大小
SetWindowPos(hWnd2, HWND_TOP, 0, 0, ww, wh, SWP_NOMOVE);
}
// 顯示視窗
ShowWindow(hWnd, nCmdShow);
// 顯示視窗2
ShowWindow(hWnd2, nCmdShow);
// 使WM_PAINT不被呼叫
ValidateRect(hWnd, 0);
// 使WM_PAINT不被呼叫
ValidateRect(hWnd2, 0);
// renderer物件
Renderer renderer;
// renderer物件2
Renderer renderer2;
// renderer初始化
HRESULT hr;
hr = renderer.Initialize(hWnd, isFullScreen, CLIENT_WIDTH,
CLIENT_HEIGHT);
if(FAILED(hr)) {
return 0; // 初始化失敗
}
// renderer初始化2
HRESULT hr2;
hr2 = renderer.Initialize(hWnd2, isFullScreen, CLIENT_WIDTH,
CLIENT_HEIGHT);
if(FAILED(hr2)) {
return 0; // 初始化失敗
}
// 場景(scene)物件
Scene scene;
// 場景(scene)物件2
Scene scene2;
// 產生場景
if(FAILED(scene.Create(renderer.GetDevice()))) {
return 0;
}
// 產生場景2
if(FAILED(scene2.Create(renderer2.GetDevice()))) {
return 0;
}
// 訊息處理以及描繪迴圈
while(TRUE) {
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
if(msg.message == WM_QUIT) {
break; // 迴圈結束
}
else {
// 訊息的翻譯以及Dispatch
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
else { // 若無處理訊息時進行描繪
// 只有在看到視窗時描繪的處理
WINDOWPLACEMENT wndpl;
GetWindowPlacement(hWnd, &wndpl); if((wndpl.showCmd != SW_HIDE) &&
(wndpl.showCmd != SW_MINIMIZE) &&
(wndpl.showCmd != SW_SHOWMINIMIZED) &&
(wndpl.showCmd != SW_SHOWMINNOACTIVE)) {
// 執行描繪處理
renderer.RenderScene(&scene);
}
}
Sleep(1);
}
// 訊息處理以及描繪迴圈2
while(TRUE) {
if(PeekMessage(&msg2, NULL, 0, 0, PM_REMOVE)) {
if(msg2.message == WM_QUIT) {
break; // 迴圈結束
}
else {
// 訊息的翻譯以及Dispatch
TranslateMessage(&msg2);
DispatchMessage(&msg2);
}
}
else { // 若無處理訊息時進行描繪
// 只有在看到視窗時描繪的處理
WINDOWPLACEMENT wndpl2;
GetWindowPlacement(hWnd2, &wndpl2);
if((wndpl2.showCmd != SW_HIDE) &&
(wndpl2.showCmd != SW_MINIMIZE) &&
(wndpl2.showCmd != SW_SHOWMINIMIZED) &&
(wndpl2.showCmd != SW_SHOWMINNOACTIVE)) {
// 執行描繪處理
renderer2.RenderScene(&scene2);
}
}
Sleep(1);
}
return (int) msg.wParam;
}
//-------------------------------------------------------------
// 訊息處理所使用的Callback
//-------------------------------------------------------------
LRESULT CALLBACK WindowProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg) {
case WM_CLOSE: // 視窗被關閉
PostQuitMessage(0); // 結束應用程式
break;
case WM_KEYDOWN: // 有鍵被按下
if (wParam == VK_ESCAPE) { // 被按下的是ESC鍵
PostQuitMessage(0); // 結束應用程式
}
break;
default:
return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
LRESULT CALLBACK WindowProc2(HWND hWnd2, UINT msg2, WPARAM wParam2, LPARAM
lParam2)
{
switch (msg2) {
case WM_CLOSE: // 視窗被關閉
PostQuitMessage(0); // 結束應用程式
break;
case WM_KEYDOWN: // 有鍵被按下
if (wParam2 == VK_ESCAPE) { // 被按下的是ESC鍵
PostQuitMessage(0); // 結束應用程式
}
break;
default:
return DefWindowProc(hWnd2, msg2, wParam2, lParam2);
}
return 0;
}
--
※ 發信站: 批踢踢實業坊(ptt.cc)
◆ From: 220.135.180.252
※ 編輯: xxx1118 來自: 140.96.76.126 (08/04 11:10)
C_and_CPP 近期熱門文章
PTT數位生活區 即時熱門文章