Displaying mesh using DirectX 9 - c++

#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.

Related

while implementing dwrite to draw a glyph of a font in c++ leads to nullptr error

I have been taking reference for my project from this source:
https://learn.microsoft.com/en-us/windows/win32/directwrite/getting-started-with-directwrite
My goal is very simple:
Follow the guidance in the link given below and somehow get the output that the link finally gets. I would have been glad if I at least got the intermediate output.
However, unfortunately my project always seems to compile with a nullptr error, and these are my findings so far. I'm working in an area out of my expertise and I was only able to find the following:
I am not sure if I have created the SimpleText class according to what has been given in the link
I am probably not linking the window handler correctly to the Simple Text class object
Here is my code(it seems big, but it is only just class definition + basic window creation, honestly nothing else at all)
// cvvvv.cpp : Defines the entry point for the application.
//
#include "framework.h"
#include "cvvvv.h"
#include<dwrite.h>
#include<d2d1.h>
#include<iostream>
#include<fstream>
#include<stdio.h>
using namespace std;
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
// *********************************************************************************
//HRESULT HasCharacter(
// UINT32 unicodeValue,
// BOOL* exists
//);
long const uniLast = 1114111;
//UINT32 codePoints[uniLast];
//UINT32 codePointsCount = uniLast;
//UINT16 glyphIndices[uniLast];
long long SairamAll;
// https://learn.microsoft.com/en-us/windows/win32/directwrite/getting-started-with-directwrite //
///// Part 1: Declare DirectWrite and Direct2D Resources. /////
// 1. In your class header file(SimpleText.h), declare pointers to IDWriteFactoryand IDWriteTextFormat interfaces as private members.
//IDWriteFactory* pDWriteFactory_;
//IDWriteTextFormat* pTextFormat_;
// 3. Declare pointers to ID2D1Factory, ID2D1HwndRenderTarget, and ID2D1SolidColorBrush interfaces for rendering the text with Direct2D.
//ID2D1Factory* pD2DFactory_;
//ID2D1HwndRenderTarget* pRT_;
//ID2D1SolidColorBrush* pBlackBrush_;
///// Part 2: Create Device Independent Resources. /////
template <class T> void SafeRelease(T** ppT)
{
if (*ppT)
{
(*ppT)->Release();
*ppT = NULL;
}
}
class SimpleText {
private:
// 2. Declare members to hold the text string to render and the length of the string.
IDWriteFactory* pDWriteFactory_;
IDWriteTextFormat* pTextFormat_;
const wchar_t* wszText_;
UINT32 cTextLength_;
ID2D1Factory* pD2DFactory_;
ID2D1HwndRenderTarget* pRT_;
ID2D1SolidColorBrush* pBlackBrush_;
HRESULT hr;
RECT rc;
HWND hwnd_;
float dpiScaleX_, dpiScaleY_;
public:
SimpleText() {
hr = CreateDeviceResources();
if (SUCCEEDED(hr))
{
pRT_->BeginDraw();
pRT_->SetTransform(D2D1::IdentityMatrix());
pRT_->Clear(D2D1::ColorF(D2D1::ColorF::White));
// Call the DrawText method of this class.
hr = DrawText();
if (SUCCEEDED(hr))
{
hr = pRT_->EndDraw(
);
}
}
if (FAILED(hr))
{
DiscardDeviceResources();
}
}
void CreateDeviceIndependentResources() {
hr = D2D1CreateFactory(
D2D1_FACTORY_TYPE_SINGLE_THREADED,
&pD2DFactory_);
if (SUCCEEDED(hr))
{
hr = DWriteCreateFactory(
DWRITE_FACTORY_TYPE_SHARED,
__uuidof(IDWriteFactory),
reinterpret_cast<IUnknown**>(&pDWriteFactory_)
);
}
wszText_ = L"Hello World using DirectWrite!";
cTextLength_ = (UINT32)wcslen(wszText_);
if (SUCCEEDED(hr))
{
hr = pDWriteFactory_->CreateTextFormat(
L"Gabriola", // Font family name.
NULL, // Font collection (NULL sets it to use the system font collection).
DWRITE_FONT_WEIGHT_REGULAR,
DWRITE_FONT_STYLE_NORMAL,
DWRITE_FONT_STRETCH_NORMAL,
72.0f,
L"en-us",
&pTextFormat_
);
}
// Center align (horizontally) the text.
if (SUCCEEDED(hr))
{
hr = pTextFormat_->SetTextAlignment(DWRITE_TEXT_ALIGNMENT_CENTER);
}
if (SUCCEEDED(hr))
{
hr = pTextFormat_->SetParagraphAlignment(DWRITE_PARAGRAPH_ALIGNMENT_CENTER);
}
}
HRESULT CreateDeviceResources() {
GetClientRect(hwnd_, &rc);
D2D1_SIZE_U size = D2D1::SizeU(rc.right - rc.left, rc.bottom - rc.top);
if (!pRT_)
{
// Create a Direct2D render target.
hr = pD2DFactory_->CreateHwndRenderTarget(
D2D1::RenderTargetProperties(),
D2D1::HwndRenderTargetProperties(
hwnd_,
size
),
&pRT_
);
// Create a black brush.
if (SUCCEEDED(hr))
{
hr = pRT_->CreateSolidColorBrush(
D2D1::ColorF(D2D1::ColorF::Black),
&pBlackBrush_
);
}
}
return hr;
}
void DiscardDeviceResources() {
SafeRelease(&pRT_);
SafeRelease(&pBlackBrush_);
}
HRESULT DrawText() {
D2D1_RECT_F layoutRect = D2D1::RectF(
static_cast<FLOAT>(rc.left) / dpiScaleX_,
static_cast<FLOAT>(rc.top) / dpiScaleY_,
static_cast<FLOAT>(rc.right - rc.left) / dpiScaleX_,
static_cast<FLOAT>(rc.bottom - rc.top) / dpiScaleY_
);
pRT_->DrawText(
wszText_, // The string to render.
cTextLength_, // The string's length.
pTextFormat_, // The text format.
layoutRect, // The region of the window where the text will be rendered.
pBlackBrush_ // The brush used to draw the text.
);
return hr;
}
};
// *********************************************************************************
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_CVVVV, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_CVVVV));
MSG msg;
SimpleText s;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW 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(hInstance, MAKEINTRESOURCE(IDI_CVVVV));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_CVVVV);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
I am sorry if I am asking for too much. But I am honestly stuck, and very surprisingly, I was not able to find this implemented anywhere on the net(hope I did not miss something that was obviously there).

Unable to add thumbnail buttons to a window?

I'm trying to add thumbnail buttons to a window, but there is no error and no thumbnail button is shown. I read the following pages for reference:
Your First Windows Program;
ITaskbarList3::ThumbBarAddButtons method;
some code on github.
Environment: win10 64bit, vs2015
// function WindowProc and wWinMain are copied from msdn directly.
#include "stdafx.h"
#include <windows.h>
#include "shobjidl.h"
#include <exception>
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
HRESULT addThumbnailButtons(HWND hwnd) {
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
if (SUCCEEDED(hr)) {
ITaskbarList4* ptbl = nullptr;
HRESULT hr = CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&ptbl));
if (SUCCEEDED(hr)) {
// create 2 buttons
THUMBBUTTON thmb[2] = {};
thmb[0].dwMask = THB_TOOLTIP;
thmb[0].iId = 0;
wcscpy_s(thmb[0].szTip, L"Button 1");
thmb[1].dwMask = THB_TOOLTIP;
thmb[1].iId = 1;
wcscpy_s(thmb[1].szTip, L"Button 2");
//ptbl->HrInit();
hr = ptbl->ThumbBarAddButtons(hwnd, ARRAYSIZE(thmb), thmb);
ptbl->Release();
return hr;
}
else {
throw std::exception("createInstance failed");
}
}else{
throw std::exception("coinitialize failed");
}
}
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
HRESULT hr = addThumbnailButtons(hwnd);
if (FAILED(hr)) {
throw std::exception("addbuttons failed");
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
}
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
Per the ITaskBarList3 documentation:
When an application displays a window, its taskbar button is created by the system. When the button is in place, the taskbar sends a TaskbarButtonCreated message to the window. Your application should call RegisterWindowMessage(L"TaskbarButtonCreated") and handle that message in its wndproc. That message must be received by your application before it calls any ITaskbarList3 method.
You must wait for that message before calling addThumbnailButtons(), eg:
UINT uMsgTaskbarCreated;
int WINAPI wWinMain(HINSTANCE hInstance, HINSTANCE, PWSTR pCmdLine, int nCmdShow)
{
uMsgTaskbarCreated = RegisterWindowMessage(L"TaskbarButtonCreated");
// Register the window class.
const wchar_t CLASS_NAME[] = L"Sample Window Class";
WNDCLASS wc = {};
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);
// Create the window.
HWND hwnd = CreateWindowEx(
0, // Optional window styles.
CLASS_NAME, // Window class
L"Learn to Program Windows", // Window text
WS_OVERLAPPEDWINDOW, // Window style
// Size and position
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
NULL, // Parent window
NULL, // Menu
hInstance, // Instance handle
NULL // Additional application data
);
if (hwnd == NULL)
{
return 0;
}
ShowWindow(hwnd, nCmdShow);
// Run the message loop.
MSG msg = {};
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return 0;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hwnd, &ps);
FillRect(hdc, &ps.rcPaint, (HBRUSH)(COLOR_WINDOW + 1));
EndPaint(hwnd, &ps);
return 0;
}
default:
if ((uMsg == uMsgTaskbarCreated) && (uMsgTaskbarCreated != 0))
{
HRESULT hr = addThumbnailButtons(hwnd);
if (FAILED(hr)) {
...;
}
}
break;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

DirectX11 ClearRenderTargetView

This fails on the ClearRenderTargetView call.
Im not sure where my error is - im following a tutorial and i hvae no clue what is incorrect.
Would appreciate some help, thanks guys!
// DX6.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "DX6.h"
#include <d3d11.h>
#include <d3dx11.h>
#include <d3d10.h>
#include <d3dx9core.h>
// include the Direct3D Library file
#pragma comment (lib, "d3d11.lib")
#pragma comment (lib, "d3dx11.lib")
#pragma comment (lib, "d3dx10.lib")
//forward declares
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
void InitD3D(HWND hWnd); // sets up and initializes Direct3D
void RenderFrame(void);
void CleanD3D(void); // closes Direct3D and releases memory
// Global Variables:
HWND hWnd;
HINSTANCE hInst;
IDXGISwapChain *swapchain; // the pointer to the swap chain interface
ID3D11Device *dev; // the pointer to our Direct3D device interface
ID3D11DeviceContext *devcon; // the pointer to our Direct3D device context
ID3D11RenderTargetView *backbuffer; // global declaration
int APIENTRY _tWinMain(HINSTANCE hInstance,HINSTANCE hPrevInstance,LPTSTR lpCmdLine,int nCmdShow)
{
WNDCLASSEX wc;
ZeroMemory(&wc,sizeof(WNDCLASSEX));
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = L"WindowClass1";
RegisterClassEx(&wc);
// TODO: Place code here.
MSG msg={0};
hInst = hInstance; // Store instance handle in our global variable
hWnd = CreateWindow(L"WindowClass1", L"Test Title", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, NULL, NULL, hInstance, NULL);
if (!hWnd)
{
return 1;
}
ShowWindow(hWnd, nCmdShow);
// Main message loop:
while (true)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);
// send the message to the WindowProc function
DispatchMessage(&msg);
// check to see if it's time to quit
if(msg.message == WM_QUIT)
break;
}
else{
RenderFrame();
}
}
return (int) msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
int wmId, wmEvent;
PAINTSTRUCT ps;
HDC hdc;
switch (message)
{
case WM_COMMAND:
wmId = LOWORD(wParam);
wmEvent = HIWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_EXIT:
DestroyWindow(hWnd);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
break;
case WM_PAINT:
hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code here...
EndPaint(hWnd, &ps);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
//D3D
void InitD3D(HWND hWnd){
DXGI_SWAP_CHAIN_DESC scd;
ZeroMemory(&scd,sizeof(DXGI_SWAP_CHAIN_DESC));
scd.BufferCount=1;
scd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; // use 32-bit color
scd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; // how swap chain is to be used
scd.OutputWindow = hWnd; // the window to be used
scd.SampleDesc.Count = 4; // how many multisamples
scd.Windowed = TRUE;
D3D11CreateDeviceAndSwapChain(NULL,D3D_DRIVER_TYPE_HARDWARE,NULL,NULL,NULL,NULL,D3D11_SDK_VERSION,&scd,&swapchain,&dev,NULL,&devcon);
ID3D11Texture2D *pBackBuffer;
swapchain->GetBuffer(0, __uuidof(ID3D11Texture2D), (LPVOID*)&pBackBuffer);
// use the back buffer address to create the render target
dev->CreateRenderTargetView(pBackBuffer, NULL, &backbuffer);
pBackBuffer->Release();
// set the render target as the back buffer
devcon->OMSetRenderTargets(1, &backbuffer, NULL);
//create viewport
D3D11_VIEWPORT viewport;
ZeroMemory(&viewport,sizeof(D3D11_VIEWPORT));
viewport.TopLeftX=0;
viewport.TopLeftY=0;
viewport.Width=800;
viewport.Height=800;
//set viewport
devcon->RSSetViewports(1,&viewport);
}
void RenderFrame(void){
//FAILS HERE!!!
//Unhandled exception at 0x002e1a9f in DX6.exe: 0xC0000005: Access violation //reading location 0x00000000.
devcon->ClearRenderTargetView(backbuffer,D3DXCOLOR(0.0f,0.2f,0.4f,1.0f));
//switch back & front buffer
swapchain->Present(0,0);
}
void CleanD3D()
{
// close and release all existing COM objects
swapchain->Release();
dev->Release();
devcon->Release();
}
You never call InitD3D, so when CreateRenderTargetView is called in RenderFrame the backbuffer has not been set yet.

direct3d initialization failure / c++

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.

Detect when mouse leaves my app

Hello I am creating an app in win32 that will display the x, y position(In screen coords) of the mouse whereever the mouse is (inside my app client/NC area & outside).
I am at the stage where I want to detect when the mouse leaves my application completely. I have written a simple win32 app that should detect & notify myself when the mouse leaves my app, BUT its not working, I never receive the messages WM_MOUSELEAVE & WM_NCMOUSELEAVE.
What do you think is wrong? Am I using the wrong win32 functions?
// Track Mouse.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include <windows.h>
#include <vector>
#include <string>
#include <cstdlib>
static HINSTANCE gInstance;
// Globals //
enum MouseStatus { DEFAULT = 50001, LEFT_CLIENT, LEFT_NCLIENT };
static MouseStatus mouseState = DEFAULT;
static COLORREF bkCol = RGB(0,255,255);
// Functions List //
BOOL TrackMouse( HWND hwnd )
{
// Post:
TRACKMOUSEEVENT mouseEvt;
ZeroMemory( &mouseEvt, sizeof(TRACKMOUSEEVENT) );
mouseEvt.cbSize = sizeof(TRACKMOUSEEVENT);
mouseEvt.dwFlags = TME_LEAVE | TME_NONCLIENT;
//mouseEvt.dwHoverTime = HOVER_DEFAULT;
mouseEvt.hwndTrack = hwnd;
return TrackMouseEvent( &mouseEvt );
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
{
// Track mouse so I can be notified when it leaves my application (Client & NC areas)
BOOL trackSuccess = TrackMouse( hwnd ); // Returns successful, so I correctly track the mouse
if ( trackSuccess == 0 )
{
MessageBoxW( hwnd, L"Failed to track mouse", L"Error", MB_OK|MB_ICONEXCLAMATION );
}
else MessageBoxW( hwnd, L"Tracking mouse", L"Success", MB_OK|MB_ICONEXCLAMATION );
}
break;
case WM_MOUSELEAVE:
{
// I never receive this message
// Detect when the mouse leaves the client area
mouseState = LEFT_CLIENT;
bkCol = RGB(50,50,50);
InvalidateRect( hwnd, NULL, true );
}
break;
case WM_NCMOUSELEAVE :
{
// I never receive this message
// If the mouse has left the client area & then leaves the NC area then I know
// that the mouse has left my app
if ( mouseState == LEFT_CLIENT )
{
mouseState = LEFT_NCLIENT;
BOOL trackSuccess = TrackMouse( hwnd );
if ( trackSuccess == 0 )
{
bkCol = RGB(255,255,0);
MessageBoxW( hwnd, L"On WM_NCMOUSELEAVE: Failed to track mouse", L"Error", MB_OK|MB_ICONEXCLAMATION );
}
else MessageBoxW( hwnd, L"On WM_NCMOUSELEAVE: Tracking mouse", L"Success", MB_OK|MB_ICONEXCLAMATION );
InvalidateRect( hwnd, NULL, true );
}
}
break;
case WM_ACTIVATE:
case WM_MOUSEHOVER:
{
// The mouse is back in my app
mouseState = DEFAULT;
bkCol = RGB(0,255,255);
InvalidateRect( hwnd, NULL, true );
}
break;
case WM_PAINT:
{
HDC hdc;
PAINTSTRUCT ps;
hdc = BeginPaint( hwnd, &ps );
SetBkColor( hdc, bkCol );
Rectangle( hdc, 10, 10, 200, 200 );
EndPaint( hwnd, &ps );
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
break;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
int WINAPI WinMain(HINSTANCE gInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG Msg;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = gInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(DKGRAY_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = L"Custom Class";
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
// if registration of main class fails
if(!RegisterClassEx(&wc))
{
MessageBoxW(NULL, L"Window Registration Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hwnd = CreateWindowEx(
WS_EX_CLIENTEDGE,
L"Custom Class",
L"App Name",
WS_CAPTION|WS_MINIMIZEBOX|WS_VISIBLE|WS_OVERLAPPED|WS_SYSMENU,
CW_USEDEFAULT, CW_USEDEFAULT, 600, 500,
NULL, NULL, gInstance, NULL);
if(hwnd == NULL)
{
MessageBoxW(NULL, L"Window Creation Failed!", L"Error!",
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
while(GetMessage(&Msg, NULL, 0, 0) > 0)
{
TranslateMessage(&Msg);
DispatchMessage(&Msg);
}
return Msg.wParam;
}
The key component your missing is SetCapture(hwnd); which directs all mouse messages to that hwnd until you call ReleaseCapture();
HANDLE_DLGMSG(hwnd, WM_RBUTTONDOWN, SKDemo_OnRButtonDown);
HANDLE_DLGMSG(hwnd, WM_MOUSEMOVE, SKDemo_OnMouseMove);
HANDLE_DLGMSG(hwnd, WM_RBUTTONUP, SKDemo_OnRButtonUp);
void SKDemo_OnRButtonDown (HWND hwnd, BOOL fDbClk, int x, int y, UINT keyFlags)
{
// Force all mouse messages to come to this window.
SetCapture(hwnd);
// Change the mouse cursor to eyes. This provides a visual indication
// to the user that Voyeur is "peering."
SetCursor(LoadCursor(GetWindowInstance(hwnd),
MAKEINTRESOURCE(IDC_POINTER)));
}
void SKDemo_OnMouseMove (HWND hwnd, short x, short y, UINT keyFlags)
{
if( GetCapture() == NULL ) {
return;
}
// do something with the message here
}
void SKDemo_OnRButtonUp (HWND hwnd, int x, int y, UINT keyFlags)
{
ReleaseCapture();
}
I think you need the mouse to be over your window before you all TrackMouseEvent. Try calling whilst you handle a mouse move message.
As written in Win32 documentation, the request expires each time the mouse leaves the window. So you need to call TrackMouseEvent also in your WM_MOUSELEAVE handler. Note also that if the mouse isn't in your window at the time TrackMouseEvent is called, WM_MOUSELEAVE is generated immediately.
The win32 API is more or less ridiculous. It doesn't have a mouse enter/leave. A google search for "MFC mouse enter leave" turned up this:
http://www.codeproject.com/KB/cpp/mouseenterleave.aspx
Note that MFC is just a thin wrapper around win32 proper. You can basically take any member function of a WND and call a C function with the exact same name and HWND as first parameter...the rest being all exactly the same.
Have fun. This kind of crap is why I hate all things win32.