this is the code that creates a simple window and initializes a simple direct3d device. but every time the program reaches the render() function application terminates. i have no idea why that happens. can somebody explain me this weird behavior? thank you!!
//====================================================================================================
#include <windows.h>
#include <d3d9.h>
//====================================================================================================
HINSTANCE hInst;
HWND wndHandle;
//====================================================================================================
LPDIRECT3D9 pD3D; // the Direct3D object
LPDIRECT3DDEVICE9 pd3dDevice; // the Direct3D device
//====================================================================================================
bool initWindow(HINSTANCE hInstance);
bool initDirect3D(void);
void cleanUp (void);
void render(void);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
//====================================================================================================
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
if (!initWindow(hInstance)) return false;
if (!initDirect3D()) return false;
MSG msg;
ZeroMemory(&msg, sizeof(msg));
if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
} else {
render(); // i think this is the problem ...
}
return static_cast<int>(msg.wParam);
}
bool initWindow(HINSTANCE hInstance )
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(0, IDI_APPLICATION);
wcex.hCursor = LoadCursor(0, IDC_ARROW);
wcex.hbrBackground = static_cast<HBRUSH>(GetStockObject(WHITE_BRUSH));
wcex.lpszMenuName = 0L;
wcex.lpszClassName = L"DirectXTemplate";
wcex.hIconSm = 0;
RegisterClassEx(&wcex);
wndHandle = CreateWindow(L"DirectXTemplate", L"DirectX Template", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);
if (!wndHandle) return false;
ShowWindow(wndHandle, SW_SHOW);
UpdateWindow(wndHandle);
return true;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
bool initDirect3D(void)
{
pD3D = NULL;
pd3dDevice = NULL;
// create the DirectX object
if(NULL == (pD3D = Direct3DCreate9(D3D_SDK_VERSION))) return false;
// fill the presentation parameters structure
D3DPRESENT_PARAMETERS d3dpp;
ZeroMemory(&d3dpp, sizeof(d3dpp));
d3dpp.Windowed = TRUE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat = D3DFMT_UNKNOWN;
d3dpp.BackBufferCount = 1;
d3dpp.BackBufferHeight = 480;
d3dpp.BackBufferWidth = 640;
d3dpp.hDeviceWindow = wndHandle;
// create a default DirectX device
if (FAILED(pD3D -> CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_REF, wndHandle, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &pd3dDevice))) return false;
return true;
}
void render(void)
{
// Check to make sure you have a valid Direct3D device
if(NULL == pd3dDevice) return; // clear the back buffer to a blue color
pd3dDevice -> Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 0, 255), 1.0f, 0);
// Present the back buffer contents to the display
pd3dDevice -> Present(NULL, NULL, NULL, NULL);
}
void cleanUp (void)
{
// Release the device and the Direct3D object
if (pd3dDevice != NULL) pd3dDevice -> Release();
if (pD3D != NULL) pD3D -> Release();
}
#DuckMaestro is right. Your program is going through the msg/render process once and is then ending. It should only end if the msg is to exit the program. Try putting in a loop like this:
while(msg.message!=WM_QUIT){
if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
} else {
render(); // i think this is the problem ...
}
}
Your...
if(PeekMessage(&msg, NULL, 0U, 0U, PM_REMOVE))
{
TranslateMessage (&msg);
DispatchMessage (&msg);
} else {
render(); // i think this is the problem ...
}
...needs to be in a while loop, no? Step through your code with a debugger, statement by statement. Win32 applications need a while loop to stay alive, so-to-speak.
Related
I'm learning about creating a Windows desktop application using Visual C++.
I am creating a simple window that does nothing, and when I press the close button, I wanted to display a message box to confirm that I really want to close it before I close the window.
So I tried to do this using the Messagebox function when I got the WM_CLOSE message, but for some reason the program froze and wouldn't close.
I'm sorry, but can someone help me out?
The source is as follows. Thank you for your help.
#include<Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);
TCHAR szClassName[] = TEXT("winapp");
int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) {
MSG msg;
BOOL bRet;
if(!InitApp(hCurInst))
return FALSE;
if (!InitInstance(hCurInst, nCmdShow))
return FALSE;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
if (bRet == -1) {
MessageBox(NULL, TEXT("GetMessageエラー"), TEXT("Error"), MB_OK);
break;
}
else {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
return (int)msg.wParam;
}
ATOM InitApp(HINSTANCE hInst) {
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = (HICON)LoadImage(
NULL,
MAKEINTRESOURCE(IDI_APPLICATION),
IMAGE_ICON,
0,
0,
LR_DEFAULTSIZE | LR_SHARED);
wc.hCursor = (HCURSOR)LoadImage(
NULL,
MAKEINTRESOURCE(IDC_ARROW),
IMAGE_CURSOR,
0,
0,
LR_DEFAULTSIZE | LR_SHARED);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.hIconSm = (HICON)LoadImage(
NULL,
MAKEINTRESOURCE(IDI_APPLICATION),
IMAGE_ICON,
0,
0,
LR_DEFAULTSIZE | LR_SHARED);
return (RegisterClassEx(&wc));
}
BOOL InitInstance(HINSTANCE hInst, int nCmdShow) {
HWND hWnd;
hWnd = CreateWindow(
szClassName,
TEXT("Winapp"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInst,
NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
int id;
switch (msg){
case WM_CLOSE:
id = MessageBox(hWnd,TEXT("終了してもよろしいですか?"),TEXT("終了確認"),MB_YESNO | MB_ICONQUESTION);
if(id==IDYES){
DestroyWindow(hWnd);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0;
}
Try explicit use of unicode in your program. for exsmple using MessageBoxW instead of MessageBox and L"終了してもよろしいですか?" instead of TEXT("終了してもよろしいですか?") and change your windowproc a bit:
#include<Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);
TCHAR szClassName[] = TEXT("winapp");
int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) {
MSG msg;
BOOL bRet;
if(!InitApp(hCurInst))
return FALSE;
if (!InitInstance(hCurInst, nCmdShow))
return FALSE;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
if (bRet == -1) {
MessageBoxW(NULL, L"GetMessageエラー", L"Error", MB_OK);
break;
}
else {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
return (int)msg.wParam;
}
ATOM InitApp(HINSTANCE hInst) {
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = (HICON)LoadImage(
NULL,
MAKEINTRESOURCE(IDI_APPLICATION),
IMAGE_ICON,
0,
0,
LR_DEFAULTSIZE | LR_SHARED);
wc.hCursor = (HCURSOR)LoadImage(
NULL,
MAKEINTRESOURCE(IDC_ARROW),
IMAGE_CURSOR,
0,
0,
LR_DEFAULTSIZE | LR_SHARED);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.hIconSm = (HICON)LoadImage(
NULL,
MAKEINTRESOURCE(IDI_APPLICATION),
IMAGE_ICON,
0,
0,
LR_DEFAULTSIZE | LR_SHARED);
return (RegisterClassEx(&wc));
}
BOOL InitInstance(HINSTANCE hInst, int nCmdShow) {
HWND hWnd;
hWnd = CreateWindow(
szClassName,
TEXT("Winapp"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInst,
NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
int id;
switch (msg){
case WM_CLOSE:
id = MessageBoxW(hWnd,L"終了してもよろしいですか?", L"終了確認",MB_YESNO | MB_ICONQUESTION);
if(id==IDYES){
DestroyWindow(hWnd);
}
return 0;
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return (DefWindowProc(hWnd, msg, wp, lp));
}
If you try to press the close button, but the MessageBox does not pop up. Try to press the ALT key to see if it pops up. I suggest you handle the WM_PAINT message to ensure that the drawing message is processed.
Code:
#include<Windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
ATOM InitApp(HINSTANCE);
BOOL InitInstance(HINSTANCE, int);
TCHAR szClassName[] = TEXT("winapp");
int WINAPI WinMain(HINSTANCE hCurInst, HINSTANCE hPrevInst, LPSTR lpsCmdLine, int nCmdShow) {
MSG msg;
BOOL bRet;
if (!InitApp(hCurInst))
return FALSE;
if (!InitInstance(hCurInst, nCmdShow))
return FALSE;
while ((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) {
if (bRet == -1) {
MessageBox(NULL, TEXT("GetMessageエラー"), TEXT("Error"), MB_OK);
break;
}
else {
TranslateMessage(&msg);
DispatchMessageW(&msg);
}
}
return (int)msg.wParam;
}
ATOM InitApp(HINSTANCE hInst) {
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = (HICON)LoadImage(
NULL,
MAKEINTRESOURCE(IDI_APPLICATION),
IMAGE_ICON,
0,
0,
LR_DEFAULTSIZE | LR_SHARED);
wc.hCursor = (HCURSOR)LoadImage(
NULL,
MAKEINTRESOURCE(IDC_ARROW),
IMAGE_CURSOR,
0,
0,
LR_DEFAULTSIZE | LR_SHARED);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = szClassName;
wc.hIconSm = (HICON)LoadImage(
NULL,
MAKEINTRESOURCE(IDI_APPLICATION),
IMAGE_ICON,
0,
0,
LR_DEFAULTSIZE | LR_SHARED);
return (RegisterClassEx(&wc));
}
BOOL InitInstance(HINSTANCE hInst, int nCmdShow) {
HWND hWnd;
hWnd = CreateWindow(
szClassName,
TEXT("Winapp"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
NULL,
NULL,
hInst,
NULL);
if (!hWnd)
return FALSE;
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wp, LPARAM lp) {
int id;
PAINTSTRUCT ps;
switch (msg) {
case WM_PAINT:
BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
return 0;
case WM_CLOSE:
id = MessageBox(hWnd, TEXT("終了してもよろしいですか?"), TEXT("終了確認"), MB_YESNO | MB_ICONQUESTION);
if (id == IDYES) {
DestroyWindow(hWnd);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return (DefWindowProc(hWnd, msg, wp, lp));
}
return 0;
}
More reference:Why would a message box be not displaying?
I am trying to learn Win32 through msdn but I am having problems with RegisterClassEx, I checked other threads stating that maybe not all members are initialized but I am sure they are.
#include <Windows.h>
#include <tchar.h>
static const TCHAR windowclass_sz[] = _T("WindowClass1");
static const TCHAR windowtitle_sz[] = _T("DirectX 12 Demo");
bool Stop = true;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM
lParam)
{
switch (message)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE PrevhInstance, LPSTR
lpCmdLine, int nCmdShow)
{
MSG msg;
HWND hWnd;
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);
wcex.hIconSm = LoadIcon(wcex.hInstance, IDI_APPLICATION);
wcex.hInstance = hInstance;
wcex.lpfnWndProc = WndProc;
wcex.lpszClassName = windowclass_sz;
wcex.lpszMenuName = nullptr;
wcex.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wcex);
if (!RegisterClassEx(&wcex))
{
GetLastError();
MessageBox(NULL, _T("RegisterClassEx Call Error!"), _T("ERROR"),
MB_ICONERROR && MB_OK );
return 1;
}
hWnd = CreateWindowEx(NULL, windowclass_sz, windowtitle_sz,
WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
800, 600, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
MessageBox(NULL, _T("CreateWindowEx Call Error!"), _T("ERROR"),
MB_ICONERROR && MB_OK);
return 1;
}
else
{
Stop = false;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
while (Stop == false)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
As you can see, the RegisterClassEx error is triggered but I have no clue what is wrong.
A message box pops up with "RegisterClassEx Call Error!" and so the program ends there, what is the problem here?
You are calling RegisterClassEx twice with the same argument. The second call will fail, since the class already exists, and GetLastError returns error code 1410 (ERROR_CLASS_ALREADY_EXISTS)1).
Solution: Register any given window class at most once.
1) You can convert error codes into human-readable representations by calling FormatMessage. Working sample code is available in this answer.
I have a non visible application that should block log off.
I tried this code:
int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpszCmdLine, int nCmdShow){if (!FindWindow("MyWind", NULL))
{
// Ensure that the common control DLL is loaded.
ghInstance = hInstance;
WNDCLASS wc;
HWND hwnd;
MSG msg;
wc.style = 0; // Class style
wc.lpfnWndProc = (WNDPROC) WndProc; // Window procedure address
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon (NULL, IDI_WINLOGO);
wc.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MyWind";
RegisterClass (&wc);
hwnd = CreateWindow (
"MyWind", // WNDCLASS name
"MyWind", // Window title
NULL, // Window style
0, // Horizontal position
200, // Vertical position
10, // Initial width
15, // Initial height
HWND_DESKTOP, // Handle of parent window
NULL, // Menu handle
hInstance, // Application's instance handle
NULL // Window-creation data
);
ShowWindow(hwnd, SW_HIDE);
UpdateWindow (hwnd);
int i = ShutdownBlockReasonCreate(hwnd, L"Block Shutdown");
DWORD dwRealErrorCode = GetLastError();
char sreason[50];
sprintf(sreason,"%d - %ld",i,dwRealErrorCode);
if(dwRealErrorCode != 0)
MessageBox(NULL,sreason,"FAIL!",MB_OK);
while (GetMessage (&msg, NULL, 0, 0)) {
TranslateMessage (&msg);
DispatchMessage (&msg);
}
ShutdownBlockReasonDestroy(hwnd);
return Helper64::WParamTo<int>(msg.wParam);
}
else
return 0;
}
LRESULT CALLBACK WndProc (HWND hwnd, UINT message, WPARAM wParam,
LPARAM lParam){ switch (message) {
//------------------------------------
case WM_QUERYENDSESSION :
{
return FALSE;
}
break;
case WM_ENDSESSION:
{
return TRUE;
}
}
the Return value of the function "ShutdownBlockReasonCreate" is "1" where the return value of GetLastError is "2"
Is there somme specific ustall or updates on windows that makes this run or no, because in other VirtualMachines (with the same configuration as my physical machine)this works perfectly.
Can anyone provide a simple clear example of ShutdownBlockReasonCreate? I've been trying to figure it out through the MSDN pages but I'm not understanding it, and I'm getting really tired of having to turn off my computer every time I try and test it and it doesn't work. If someone is familiar and can provide a concise example that would be awesome!
This is what I have so far, but I do'
#include <Windows.h>
#include <iostream>
std::wstring s2ws(const std::string& s)
{
int len;
int slength = (int)s.length() + 1;
len = MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, 0, 0);
wchar_t* buf = new wchar_t[len];
MultiByteToWideChar(CP_ACP, 0, s.c_str(), slength, buf, len);
std::wstring r(buf);
delete[] buf;
return r;
}
int main(int argc, char* argv[])
{
if (ShutdownBlockReasonCreate(GetForegroundWindow(), s2ws("TEST").c_str()) != 0)
std::cout << "Success" << std::endl;
else
std::cout << "Failure" << std::endl;
while (1)
{
Sleep(1000);
std::cout << "Testing..." << std::endl;
}
}
This works for me in Windows 7. You could also do it in a console program if you liked, this was a simpler example to write. You should add error checking, I didn't to keep it short.
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
HINSTANCE hInst;
HWND hWnd;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch(message)
{
case WM_QUERYENDSESSION:
return FALSE;
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_CREATE:
ShutdownBlockReasonCreate(hWnd, L"Don't do it!");
break;
case WM_DESTROY:
ShutdownBlockReasonDestroy(hWnd);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"TestClass";
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
RECT sz = {0, 0, 512, 512};
AdjustWindowRect(&sz, WS_OVERLAPPEDWINDOW, TRUE);
hWnd = CreateWindow(L"TestClass", L"Test Window", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, sz.right - sz.left, sz.bottom - sz.top,
NULL, NULL, hInstance, NULL);
if(!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
MyRegisterClass(hInstance);
if(!InitInstance(hInstance, nCmdShow))
{
return FALSE;
}
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
A console version doesn't need to be drastically different, although you do need to create a window and run a message pump so I'm not sure what it buys you over a GUI app. Obviously if you want to do work in either version you'll most likely end up needing a separate thread for the window or for your work.
Here's the simplest example of a console program I came up with. You'll notice it's almost identical other than the ConsoleCtrlHandler to intercept the various ways of closing the console window and killing the GUI window instead. It's also expected to be a MBCS project since I didn't want to change it in my test console project.
#include <SDKDDKVer.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
HINSTANCE hInst;
HWND hWnd;
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
PAINTSTRUCT ps;
HDC hdc;
switch(message)
{
case WM_QUERYENDSESSION:
return FALSE;
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
EndPaint(hWnd, &ps);
break;
case WM_CREATE:
ShutdownBlockReasonCreate(hWnd, L"Don't do it!");
break;
case WM_DESTROY:
ShutdownBlockReasonDestroy(hWnd);
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "TestClass";
wcex.hIconSm = NULL;
return RegisterClassEx(&wcex);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance;
RECT sz = {0, 0, 512, 512};
AdjustWindowRect(&sz, WS_OVERLAPPEDWINDOW, TRUE);
hWnd = CreateWindow("TestClass", "Test Window", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, sz.right - sz.left, sz.bottom - sz.top,
NULL, NULL, hInstance, NULL);
if(!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
BOOL WINAPI ConsoleCtrlHandler(DWORD dwCtrlType)
{
if(dwCtrlType == CTRL_C_EVENT ||
dwCtrlType == CTRL_BREAK_EVENT ||
dwCtrlType == CTRL_CLOSE_EVENT)
{
SendMessage(hWnd, WM_CLOSE, 0, 0);
return TRUE;
}
return FALSE;
}
int main()
{
SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE);
HINSTANCE hInstance = GetModuleHandle(NULL);
MyRegisterClass(hInstance);
if(!InitInstance(hInstance, SW_HIDE))
{
return FALSE;
}
MSG msg;
while(GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
As you can probably guess by now, ShutdownBlockReasonCreate() does not actually block shutdown. All it does is tell Windows what message to say when it pops up this screen.
To block shutdown on Windows, you need to have a window. This means that you will need to write a GUI program that uses a standard message pump. WM_QUERYENDSESSION is a message that is sent to all windows when the system wants to shut down. You can handle the message to block the shutdown request. But to understand this, you will need to understand Windows GUI programming. (You might not need an actual GUI; a message-only window might work. I don't know for sure.)
Your first question on the matter was about blocking shutdown from a system service. I am not an expert on Windows services so I don't know the answer to that. Services should not have GUIs due to running on session 0, however. I don't know if they can have message-only windows either.
#include <windows.h>
#include <d3d9.h>
#include <D3DX9Mesh.h>
#define THROW_ERROR_AND_EXIT(x) { \
MessageBox(0,x,0,0); \
return -1; \
}
LRESULT CALLBACK WndProc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )
{
// Handle close event
switch( msg )
{
case WM_DESTROY:
PostQuitMessage( 0 );
return 0;
}
return DefWindowProc( hWnd, msg, wParam, lParam );
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
// Registering class
WNDCLASSEX wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style= CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc= (WNDPROC)WndProc;
wcex.cbClsExtra= 0;
wcex.cbWndExtra= 0;
wcex.hInstance= hInstance;
wcex.hIcon= 0;
wcex.hCursor= LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground= (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName= 0;
wcex.lpszClassName= "MyMeshViewer";
wcex.hIconSm= 0;
RegisterClassEx(&wcex);
// Creating Window
HWND hWnd = CreateWindow("MyMeshViewer", "MyMeshViewer", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
// Creating Direct3D object
LPDIRECT3D9 d3dObject=NULL;
LPDIRECT3DDEVICE9 d3dDevice=NULL;
d3dObject=Direct3DCreate9(D3D_SDK_VERSION);
// Creating Direct3D device
if(NULL == d3dObject)
THROW_ERROR_AND_EXIT("NULL == d3dObject");
D3DPRESENT_PARAMETERS presParams;
ZeroMemory(&presParams,sizeof(presParams));
presParams.Windowed=TRUE;
presParams.SwapEffect=D3DSWAPEFFECT_DISCARD;
presParams.BackBufferFormat=D3DFMT_UNKNOWN;
presParams.PresentationInterval=D3DPRESENT_INTERVAL_ONE;
HRESULT hr=d3dObject->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd, D3DCREATE_HARDWARE_VERTEXPROCESSING, &presParams, &d3dDevice);
if(FAILED(hr))
THROW_ERROR_AND_EXIT("d3dObject->CreateDevice");
// Rendering
d3dDevice->Clear(0,NULL,D3DCLEAR_TARGET, D3DCOLOR_XRGB(0,255,0),1.0f,0);
d3dDevice->BeginScene();
// Loading the mesh
LPD3DXBUFFER materialBuffer = NULL;
DWORD numMaterials = 0;
LPD3DXMESH mesh = NULL;
hr=D3DXLoadMeshFromX("tiger.x", D3DXMESH_SYSTEMMEM,
d3dDevice, NULL,
&materialBuffer,NULL, &numMaterials,
&mesh );
if(FAILED(hr))
THROW_ERROR_AND_EXIT("hr=D3DXLoadMeshFromX");
// Loading the material buffer
D3DXMATERIAL* d3dxMaterials = (D3DXMATERIAL*)materialBuffer->GetBufferPointer();
// Holding material and texture pointers
D3DMATERIAL9 *meshMaterials = new D3DMATERIAL9[numMaterials];
LPDIRECT3DTEXTURE9 *meshTextures = new LPDIRECT3DTEXTURE9[numMaterials];
// Filling material and texture arrays
for (DWORD i=0; i<numMaterials; i++)
{
// Copy the material
meshMaterials[i] = d3dxMaterials[i].MatD3D;
// Set the ambient color for the material (D3DX does not do this)
meshMaterials[i].Ambient = meshMaterials[i].Diffuse;
// Create the texture if it exists - it may not
meshTextures[i] = NULL;
if (d3dxMaterials[i].pTextureFilename)
D3DXCreateTextureFromFile(d3dDevice, d3dxMaterials[i].pTextureFilename, &meshTextures[i]);
}
materialBuffer->Release();
for (DWORD i=0; i<numMaterials; i++)
{
// Set the material and texture for this subset
d3dDevice->SetMaterial(&meshMaterials[i]);
d3dDevice->SetTexture(0,meshTextures[i]);
// Draw the mesh subset
mesh->DrawSubset( i );
}
d3dDevice->EndScene();
d3dDevice->Present(NULL, NULL, NULL, NULL);
// Show Window
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
// Handle messages
MSG msg;
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
This is my program to load a mesh tiger.x and display it. But it is not getting displayed. The value of the variable numMaterials remains 1 all the time. I guess there is some issue with my program. Someone please help me to figure it out. Thanks.
The tiger.x mesh file below
http://pastebin.com/DuvpS4mh
The problem is that you are rendering to the window and then calling UpdateWindow which forces a re-paint, thus erasing the drawing.
I suggest you download the DirectX SDK and look at the samples to see how to build a 'correct' rendering loop.
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_PAINT:
{
// Rendering
d3dDevice->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 255, 0), 1.0f, 0);
d3dDevice->BeginScene();
for (DWORD i = 0; i < numMaterials; i++)
{
// Set the material and texture for this subset
d3dDevice->SetMaterial(&meshMaterials[i]);
d3dDevice->SetTexture(0, meshTextures[i]);
// Draw the mesh subset
mesh->DrawSubset(i);
}
d3dDevice->EndScene();
d3dDevice->Present(NULL, NULL, NULL, NULL);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
You have to handle the WM_PAINT event.