Visual c++ DirectX compilation error - visual-c++

Can any one help me with this error ?
And I have Linked to d3d10.lib and d3dx10.lib.
I am new to directX stuff and I was following wendy jones DirectX 10 toturial
1>t1.obj : error LNK2019: unresolved external symbol _D3D10CreateDeviceAndSwapChain#32 referenced in function "bool cdecl InitDirect3D(struct HWND *,int,int)" (?InitDirect3D##YA_NPAUHWND__##HH#Z)
1>C:\Users\Ehsan\Documents\Visual Studio 2010\Projects\DirectX\t1\Debug\t1.exe : fatal error LNK1120: 1 unresolved externals
source code :
// t1.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "windows.h"
#include "tchar.h"
#include <d3d10.h>
#include <d3dx10.h>
// Global Variables:
HINSTANCE hInst; // global handle to hold the application instance
HWND wndHandle; // global variable to hold the window handle
int width = 640;
int height = 480;
// Direct3D global vars
ID3D10Device * pD3DDevice = NULL;
IDXGISwapChain * pSwapChain = NULL;
ID3D10RenderTargetView * pRenderTargetView = NULL;
// Forward declarations of functions included in this code module:
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
bool InitWindow( HINSTANCE hInstance, int width, int height );
void Render();
void ShutDownDirect3D();
bool InitDirect3D(HWND hWnd, int width, int height);
int APIENTRY _tWinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPTSTR lpCmdLine,
int nCmdShow)
{
// TODO: Place code here.
MSG msg = {0};
// Perform application initialization:
if ( !InitWindow( hInstance, width, height ) )
{
return FALSE;
}
// called after creating the window
if(!InitDirect3D(wndHandle, width, height))
{
return FALSE;
}
//hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_T1));
// Main message loop:
while (WM_QUIT != msg.message)
{
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) == TRUE)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// Call the render function
Render();
}
ShutDownDirect3D();
return (int) msg.wParam;
}
bool InitWindow(HINSTANCE hInstance, int width, int height)
{
WNDCLASSEX wcex;
// Fill in the WNDCLASSEX structure. This describes how the window
// will look to the system
wcex.cbSize = sizeof(WNDCLASSEX); // the size of the structure
wcex.style = CS_HREDRAW | CS_VREDRAW; // the class style
wcex.lpfnWndProc = (WNDPROC)WndProc; // the window procedure callback
wcex.cbClsExtra = 0; // extra bytes to allocate for this class
wcex.cbWndExtra = 0; // extra bytes to allocate for this instance
wcex.hInstance = hInstance; // handle to the application instance
wcex.hIcon = 0; // icon to associate with the application
wcex.hCursor = LoadCursor(NULL, IDC_ARROW); // the default cursor to use
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // the background color
wcex.lpszMenuName = NULL; // the resource name for the menu
wcex.lpszClassName = TEXT("DirectXExample"); // the class name being created
wcex.hIconSm = 0; // the handle to the small icon
RegisterClassEx(&wcex);
// Resize the window
RECT rect = { 0, 0, width, height };
AdjustWindowRect(&rect, WS_OVERLAPPEDWINDOW, FALSE);
// create the window from the class above
wndHandle = CreateWindow(TEXT("DirectXExample"),
TEXT("DirectXExample"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
rect.right - rect.left,
rect.bottom - rect.top,
NULL,
NULL,
hInstance,
NULL);
if (!wndHandle)
{
return false;
}
// Display the window on the screen
ShowWindow(wndHandle, SW_SHOW);
UpdateWindow(wndHandle);
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)
{
// Check any available messages from the queue
switch (message)
{
// Allow the user to press the Escape key to end the application
case WM_KEYDOWN:
switch(wParam)
{
// Check if the user hit the Escape key
case VK_ESCAPE:
PostQuitMessage(0);
break;
}
break;
// The user hit the close button, close the application
case WM_DESTROY:
PostQuitMessage(0);
break;
}
// Always return the message to the default window procedure for furtherprocessing
return DefWindowProc(hWnd, message, wParam, lParam);
}
/*******************************************************************
* InitDirect3D
* Initializes Direct3D
* Inputs - Parent window handle - HWND,
Window width - int
Window height - int
Updating the Code 31
* Outputs - true if successful, false if failed - bool
*******************************************************************/
bool InitDirect3D(HWND hWnd, int width, int height)
{
// Create the clear the DXGI_SWAP_CHAIN_DESC structure
DXGI_SWAP_CHAIN_DESC swapChainDesc;
ZeroMemory(&swapChainDesc, sizeof(swapChainDesc));
// Fill in the needed values
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Width = width;
swapChainDesc.BufferDesc.Height = height;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = hWnd;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Windowed = TRUE;
// Create the D3D device and the swap chain
HRESULT hr = D3D10CreateDeviceAndSwapChain(NULL,
D3D10_DRIVER_TYPE_REFERENCE,
NULL,
0,
D3D10_SDK_VERSION,
&swapChainDesc,
&pSwapChain,
&pD3DDevice);
// Error checking. Make sure the device was created
if (hr != S_OK)
{
return false;
}
// Get the back buffer from the swapchain
ID3D10Texture2D * pBackBuffer;
hr = pSwapChain->GetBuffer(0, __uuidof(ID3D10Texture2D), (LPVOID*) &pBackBuffer);
if (hr != S_OK)
{
return false;
}
// create the render target view
hr = pD3DDevice->CreateRenderTargetView(pBackBuffer, NULL, &pRenderTargetView);
// release the back buffer
pBackBuffer->Release();
// Make sure the render target view was created successfully
if (hr != S_OK)
{
return false;
}
// set the render target
pD3DDevice->OMSetRenderTargets(1, &pRenderTargetView, NULL);
// create and set the viewport
D3D10_VIEWPORT viewport;
viewport.Width = width;
viewport.Height = height;
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
pD3DDevice->RSSetViewports(1, &viewport);
return true;
}
/*******************************************************************
* ShutdownDirect3D
* Closes down and releases the resources for Direct3D
34 Chapter 2 n Your First DirectX Program
* Inputs - void
* Outputs - void
*******************************************************************/
void ShutDownDirect3D()
{
// release the rendertarget
if(pRenderTargetView)
{
pRenderTargetView->Release();
}
// release the swapchain
if(pSwapChain)
{
pSwapChain->Release();
}
// release the D3D Device
if(pD3DDevice)
{
pD3DDevice->Release();
}
}
/*******************************************************************
* Render
* All drawing happens in the Render function
* Inputs - void
* Outputs - void
*******************************************************************/
void Render()
{
if (pD3DDevice != NULL)
{
// clear the target buffer
pD3DDevice->ClearRenderTargetView(pRenderTargetView, D3DXCOLOR(0.0f, 0.0f, 0.0f, 0.0f));
// All drawing will go here.
// display the next item in the swap chain
pSwapChain->Present(0, 0);
}
}

It's a problem of linkage, did you add the right library in your visual studio ?

Add D3D10.lib to the list of linker dependencies.

What about your include folder in your hard drive?
You need to go to that through your includes and also added in lib/86 to library dependances.
Follow the steps in this link: http://www.rastertek.com/dx10tut01.html
This will take you through the process of setting up DirectX. Worst happens and you do it and you still get the same problem, you know its not a linker issue. Which 4 people have now told you it is.
Also this site is great for taking you through DirectX as well. I highly advise.

Related

Is there a way to create GLX context after Xlib's window creation?

I'm trying to create OpenGLx context after the Xlib's window creation. I'm trying to separate the Xlib window creation and opengl context creation into two different phases.
Win32 window-opengl context creation was rather simple but I couldnt find any resource that illustrates the same process with Xlib-opengl in linux
This is how its done for xlib-linux
GLint glxAttribs[] = {
GLX_RGBA,
GLX_DOUBLEBUFFER,
GLX_DEPTH_SIZE, 24,
GLX_STENCIL_SIZE, 8,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_SAMPLE_BUFFERS, 0,
GLX_SAMPLES, 0,
None
};
XVisualInfo* visual = glXChooseVisual(display, screenId, glxAttribs);
XSetWindowAttributes windowAttribs;
windowAttribs.border_pixel = BlackPixel(display, screenId);
windowAttribs.background_pixel = WhitePixel(display, screenId);
windowAttribs.override_redirect = True;
windowAttribs.colormap = XCreateColormap(display, RootWindow(display, screenId), visual->visual, AllocNone);
windowAttribs.event_mask = ExposureMask;
window = XCreateWindow(display, RootWindow(display, screenId), 0, 0, 320, 200, 0, visual->depth, InputOutput, visual->visual, CWBackPixel | CWColormap | CWBorderPixel | CWEventMask, &windowAttribs);
This is how its done in windows
const WindowsWindow* pWin32Window = (const WindowsWindow*)pOwnerWindow;
HWND windowHandle = pWin32Window->GetWin32WindowHandle();
HDC windowDeviceContext = pWin32Window->GetWin32WindowDeviceContext();
/*
* Create pixel format
*/
PIXELFORMATDESCRIPTOR pfd = { sizeof(pfd),1 };
memset(&pfd, 0, sizeof(PIXELFORMATDESCRIPTOR));
pfd.nSize = sizeof(PIXELFORMATDESCRIPTOR);
pfd.dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
pfd.iPixelType = PFD_TYPE_RGBA;
pfd.nVersion = 1;
pfd.cColorBits = OpenGLDeviceUtilsWin32::GetColorBits(desc.SwapchainBufferFormat);
pfd.cAlphaBits = OpenGLDeviceUtilsWin32::GetAlphaBits(desc.SwapchainBufferFormat);
pfd.cDepthBits = OpenGLDeviceUtilsWin32::GetDepthBits(desc.SwapchainDepthStencilBufferFormat);
pfd.cStencilBits = OpenGLDeviceUtilsWin32::GetStencilBits(desc.SwapchainDepthStencilBufferFormat);
pfd.cAuxBuffers = 3;
pfd.iLayerType = PFD_MAIN_PLANE;
const int pixelFormatIndex = ChoosePixelFormat(windowDeviceContext, &pfd);
ASSERT(pixelFormatIndex != 0,"OpenGLDevice","Invalid pixel format");
ASSERT(SetPixelFormat(windowDeviceContext, pixelFormatIndex, &pfd), "OpenGLDevice", "Win32 window rejected the specified pixel format");
HGLRC tempContext = wglCreateContext(windowDeviceContext);
ASSERT(tempContext != NULL, "OpenGLDevice", "Creation of wgl dummy context failed!");
wglMakeCurrent(windowDeviceContext, tempContext);
PFNWGLCREATECONTEXTATTRIBSARBPROC wglCreateContextAttribsARB = NULL;
wglCreateContextAttribsARB = (PFNWGLCREATECONTEXTATTRIBSARBPROC)wglGetProcAddress("wglCreateContextAttribsARB");
ASSERT(wglCreateContextAttribsARB != NULL, "OpenGLDevice", "WGL get proc address failed!");
But I would expect something like this.
Create xlib window
Check for glx attribs if the window can support that pixel format
Create glx context using pixel format
But instead it goes as
Create window with your specific glx attribs
Create glx context
I wonder if there is a way for us to create window without letting xlib know we are going to use it for opengl and implement OpenGL specific setup for window creation process.
I'm trying to create OpenGLx context after the Xlib's window creation.
I don't really see your problem. On Win32 the usual stanza is:
Create window
Select pixelformat
Set pixelformat on window
Get HDC from window and use it to create context
On GLX the stanza is:
Select visual for window
Create window that's compatible with visual
Create OpenGL context with the selected visual
Take note that in both Win32 and GLX there is no hard tie between the window and the OpenGL context. As long as the pixelformat/visual of a OpenGL context and a window are compatiple, you can use them with each other.
The only difference between GLX and Win32 is, how the pixelformat/visual is communicated to OpenGL context creation. In GLX it's done directy, in Win32 the pixelformat is communicated in a rather convoluted way by means of the HDC of a window. And take note that in order to obtain a modern OpenGL context you actually have to go the route of OpenGL context creation with attributes which works exactly the same in Win32 and GLX (with Win32 needing the added steps of creating a dummy OpenGL context first in order to obtain the function pointers to the wglCreateContextAttribsARB functions, which are directly available in GLX).
Honestly, I do not understand your motivation.
Many implementations like GLFW gets Visual from GLX/EGL APIs (including glXChooseFBConfig) and use it when creating a window. The GLX/EGL stuff part can be abstracted by writing wrappers, so I don't see the need to go to the trouble of avoiding it.
That being said, it is still possible to avoid it, so I wrote the sample code for you.
// To build, execute the command below.
// c++ -Wall -Wextra -std=c++17 -o main main.cpp -lX11 -lGLX -lGL
#include <cstdio>
#include <chrono>
#include <thread>
#include <sys/time.h>
#include <unistd.h>
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <GL/glx.h>
#include <GL/glxext.h>
#define OGL_MAJOR_VERSION 3
#define OGL_MINOR_VERSION 3
#define WINDOW_WIDTH 640
#define WINDOW_HEIGHT 360
#define FPS 60
static double get_time() {
static timeval s_tTimeVal;
gettimeofday(&s_tTimeVal, NULL);
double time = s_tTimeVal.tv_sec * 1000.0; // sec to ms
time += s_tTimeVal.tv_usec / 1000.0; // us to ms
return time;
}
struct TestWindowConfig {
int width = 640;
int height = 360;
};
class TestWindow final {
public:
explicit TestWindow(const TestWindowConfig& config) : m_config(config) {}
virtual ~TestWindow() {
if (m_display) {
if (m_xid) {
XDestroyWindow(m_display, m_xid);
}
XCloseDisplay(m_display);
}
}
bool create() {
m_display = XOpenDisplay(NULL);
if (!m_display) {
fprintf(stderr, "XOpenDisplay() failed\n");
return false;
}
XSetWindowAttributes x_attr;
x_attr.override_redirect = False;
x_attr.border_pixel = 0;
m_xid = XCreateWindow(m_display, DefaultRootWindow(m_display), 0, 0, m_config.width,
m_config.height, 0, CopyFromParent, InputOutput, CopyFromParent,
CWOverrideRedirect | CWBorderPixel, &x_attr);
if (!m_xid) {
fprintf(stderr, "XOpenDisplay() failed\n");
return false;
}
XStoreName(m_display, m_xid, "X11-GLX Sample");
XMapWindow(m_display, m_xid);
m_wm_delete_window = XInternAtom(m_display, "WM_DELETE_WINDOW", True);
XSetWMProtocols(m_display, m_xid, &m_wm_delete_window, 1);
return true;
}
void show() const {
if (m_display && m_xid) {
XMapRaised(m_display, m_xid);
}
}
bool poll_events() {
if (!m_display) {
fprintf(stderr, "Display is null\n");
return false;
}
while (XPending(m_display) > 0) {
XEvent ev;
XNextEvent(m_display, &ev);
if (ev.type == ClientMessage) {
if ((Atom)ev.xclient.data.l[0] == m_wm_delete_window) {
m_should_close = true;
}
}
}
return true;
}
bool should_close() const { return m_should_close; }
Display* display() const { return m_display; }
Window xid() const { return m_xid; }
int screen_id() const { return DefaultScreen(m_display); }
private:
TestWindowConfig m_config;
Display* m_display = nullptr;
Window m_xid = 0;
Atom m_wm_delete_window;
bool m_should_close = false;
};
class TestGLContext final {
public:
explicit TestGLContext() = default;
virtual ~TestGLContext() = default;
bool create(const TestWindow& window) {
// clang-format off
int visual_attr[] = {
GLX_DRAWABLE_TYPE, GLX_WINDOW_BIT,
GLX_RENDER_TYPE, GLX_RGBA_BIT,
GLX_RED_SIZE, 8,
GLX_GREEN_SIZE, 8,
GLX_BLUE_SIZE, 8,
GLX_ALPHA_SIZE, 8,
GLX_DEPTH_SIZE, 0,
GLX_STENCIL_SIZE, 0,
GLX_DOUBLEBUFFER, True,
None
};
// clang-format on
int cfg_count;
auto fb_configs =
glXChooseFBConfig(window.display(), window.screen_id(), visual_attr, &cfg_count);
if (!fb_configs || (cfg_count < 1)) {
fprintf(stderr, "glXChooseFBConfig(): No config found\n");
return false;
}
PFNGLXCREATECONTEXTATTRIBSARBPROC glXCreateContextAttribsARB =
(PFNGLXCREATECONTEXTATTRIBSARBPROC)glXGetProcAddressARB(
(const GLubyte*)"glXCreateContextAttribsARB");
if (!glXCreateContextAttribsARB) {
fprintf(stderr, "Failed to load glXCreateContextAttribsARB\n");
return false;
}
// clang-format off
int ctx_attr[] = {
GLX_CONTEXT_PROFILE_MASK_ARB, GLX_CONTEXT_CORE_PROFILE_BIT_ARB,
GLX_CONTEXT_MAJOR_VERSION_ARB, OGL_MAJOR_VERSION,
GLX_CONTEXT_MINOR_VERSION_ARB, OGL_MINOR_VERSION,
0, 0
};
// clang-format on
m_ctx = glXCreateContextAttribsARB(window.display(), fb_configs[0], NULL, True, ctx_attr);
if (!m_ctx) {
fprintf(stderr, "Failed to create GLX Context\n");
return false;
}
m_should_destroy = true;
return true;
}
bool make_current(const TestWindow& window) {
if (glXMakeCurrent(window.display(), window.xid(), m_ctx) != True) {
fprintf(stderr, "glXMakeCurrent() Failed\n");
return false;
}
return true;
}
void swap_buffers(const TestWindow& window) { glXSwapBuffers(window.display(), window.xid()); }
static void* get_proc_address(const char* name) {
return reinterpret_cast<void*>(glXGetProcAddress((const GLubyte*)name));
}
void destroy(const TestWindow& window) {
glXDestroyContext(window.display(), m_ctx);
m_should_destroy = false;
}
bool should_destroy() const { return m_should_destroy; }
private:
GLXContext m_ctx;
bool m_should_destroy = false;
};
int main() {
// 1. Prepare Window and OpenGL Context
// In normal design, TestWindow should have its GLContext within itself.
// But, in order to fit your needs, I separated these explicitly.
TestWindowConfig config{.width = WINDOW_WIDTH, .height = WINDOW_HEIGHT};
TestWindow window{config};
TestGLContext glctx{};
if (!window.create()) {
return 1;
}
if (!glctx.create(window) || !glctx.make_current(window)) {
if (glctx.should_destroy()) {
glctx.destroy(window);
}
return 1;
}
// 2. Load OpenGL functions
// In normal cases, you are always recommended to use loader libraries like glad.
// In this example, I omited the loading part.
//
// if (!gladLoadGLLoader((GLADloadproc)glctx.get_proc_address)) {
// fprintf(stderr, "Failed to load OpenGL functions\n");
// return 1;
// }
// 3. Show the window and call OpenGL APIs
// As above, there are various problems in this implentation for real use.
window.show();
double last_time = get_time();
while (true) {
if (!window.poll_events() || window.should_close()) {
break;
}
auto delta_ms = get_time() - last_time;
if (auto diff = (1000.0 / FPS) - delta_ms; diff > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds((long)diff));
continue;
}
// fprintf(stderr, "delta: %f\n", delta_ms);
glViewport(0, 0, config.width, config.height);
glClearColor(0.0f, 0.0f, 1.0f, 1.0f);
glClear(GL_COLOR_BUFFER_BIT);
glctx.swap_buffers(window);
last_time = get_time();
}
glctx.destroy(window);
return 0;
}

How to change the background properties of an mfc application

CURRENT UI
NEW UI
I want to change the background color of a button in MFC application. I have created my user interface(UI) in MFC .I have added every controls from the toolbox.But the problem is that i want to change the background and foreground properties of a button and window.How it is possible?
please help me to change the properties of controls in MFC.In windows application we can directly change the properties in the property window.
But in the case of MFC application that is not possible.
please help me..i have not enough experience in MFC application development.....
Thanks in advance......................
code from dialer.h
class CButtonDialer : public CButton
{
// Construction
public:
CButtonDialer();
// Attributes
public:
CButton m_button;
// CButton IDC_KEY_1;
CBrush m_brush;
// Operations
public:
// Overrides
// ClassWizard generated virtual function overrides
//{{AFX_VIRTUAL(CButtonDialer)
public:
virtual void DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct);
// Implementation
public:
virtual ~CButtonDialer();
// Generated message map functions
protected:
//{{AFX_MSG(CButtonDialer)
// NOTE - the ClassWizard will add and remove member functions here.
//}}AFX_MSG
afx_msg BOOL OnEraseBkgnd(CDC* pDC);
CFont m_FontLetters;
CMapStringToString m_map;
HTHEME m_hTheme;
void OpenTheme() { m_hTheme = OpenThemeData(m_hWnd, L"Button"); }
void CloseTheme() {
if (m_hTheme) { CloseThemeData(m_hTheme); m_hTheme = NULL; }
}
DECLARE_MESSAGE_MAP()
virtual void PreSubclassWindow();
afx_msg LRESULT OnThemeChanged();
afx_msg void OnMouseMove(UINT,CPoint);
afx_msg void OnSize(UINT type, int w, int h);
};
code from dialer.cpp file
#include "stdafx.h"
#include "ButtonDialer.h"
#include "Strsafe.h"
#include "const.h"
/////////////////////////////////////////////////////////////////////////////
// CButtonDialer
CButtonDialer::CButtonDialer()
{
//255,255,255
m_brush.CreateSolidBrush(
(173, 41, 41));
m_map.SetAt(_T("1"),_T(""));
m_map.SetAt(_T("2"),_T("ABC"));
m_map.SetAt(_T("3"),_T("DEF"));
m_map.SetAt(_T("4"),_T("GHI"));
m_map.SetAt(_T("5"),_T("JKL"));
m_map.SetAt(_T("6"),_T("MNO"));
m_map.SetAt(_T("7"),_T("PQRS"));
m_map.SetAt(_T("8"),_T("TUV"));
m_map.SetAt(_T("9"),_T("WXYZ"));
m_map.SetAt(_T("0"),_T(""));
m_map.SetAt(_T("*"),_T(""));
m_map.SetAt(_T("#"),_T(""));
}
CButtonDialer::~CButtonDialer()
{
CloseTheme();
}
BEGIN_MESSAGE_MAP(CButtonDialer, CButton)
ON_WM_THEMECHANGED()
ON_WM_MOUSEMOVE()
ON_WM_SIZE()
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CButtonDialer message handlers
void CButtonDialer::PreSubclassWindow()
{
OpenTheme();
HFONT hFont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
LOGFONT lf;
GetObject(hFont, sizeof(LOGFONT), &lf);
lf.lfHeight = 14;
StringCchCopy(lf.lfFaceName,LF_FACESIZE,_T("Microsoft Sans Serif"));
m_FontLetters.CreateFontIndirect(&lf);
DWORD dwStyle = ::GetClassLong(m_hWnd, GCL_STYLE);
dwStyle &= ~CS_DBLCLKS;
::SetClassLong(m_hWnd, GCL_STYLE, dwStyle);
}
LRESULT CButtonDialer::OnThemeChanged()
{
CloseTheme();
OpenTheme();
return 0L;
}
void CButtonDialer::OnSize(UINT type, int w, int h)
{
CButton::OnSize(type, w, h);
}
void CButtonDialer::OnMouseMove(UINT nFlags,CPoint point)
{
CRect rect;
GetClientRect(&rect);
if (rect.PtInRect(point)) {
if (GetCapture() != this) {
SetCapture();
Invalidate();
}
}
else {
ReleaseCapture();
Invalidate();
}
CButton::OnMouseMove(nFlags, point);
}
void CButtonDialer::DrawItem(LPDRAWITEMSTRUCT lpDrawItemStruct)
{
CDC dc;
dc.Attach(lpDrawItemStruct->hDC); //Get device context object
CRect rt;
rt = lpDrawItemStruct->rcItem; //Get button rect
dc.FillSolidRect(rt,dc.GetBkColor());
dc.SetBkMode(TRANSPARENT);
CRect rtl = rt;
UINT state = lpDrawItemStruct->itemState; //Get state of the button
if (!m_hTheme) {
UINT uStyle = DFCS_BUTTONPUSH;
if ( (state & ODS_SELECTED) ) {
uStyle |= DFCS_PUSHED;
rtl.left+=1;
rtl.top+=1;
}
dc.DrawFrameControl(rt, DFC_BUTTON, uStyle);
} else {
UINT uStyleTheme = RBS_NORMAL;
if ( (state & ODS_SELECTED) ) {
uStyleTheme = PBS_PRESSED;
} else if (GetCapture()==this) {
uStyleTheme = PBS_HOT;
}
DrawThemeBackground(m_hTheme, dc.m_hDC,
BP_PUSHBUTTON, uStyleTheme,
rt, NULL);
}
CString strTemp;
GetWindowText(strTemp); // Get the caption which have been set
rtl.top += 4;
CString letters;
COLORREF crOldColor;
if (m_map.Lookup(strTemp,letters)) {
rtl.left+=15;
dc.DrawText(strTemp,rtl,DT_LEFT|DT_TOP|DT_SINGLELINE); // Draw out the caption
HFONT hOldFont = (HFONT)SelectObject(dc.m_hDC, m_FontLetters);
// Do your text drawing
rtl.left += 13;
rtl.top += 4;
rtl.right -=4;
crOldColor = dc.SetTextColor(RGB(148, 167, 70));
dc.DrawText(letters,rtl,DT_LEFT | DT_TOP | DT_SINGLELINE);
dc.SetTextColor(crOldColor);
// Always select the old font back into the DC
SelectObject(dc.m_hDC, hOldFont);
} else {
//127,127,127
crOldColor = dc.SetTextColor(RGB(148, 167, 70));
dc.DrawText(strTemp,rtl,DT_CENTER|DT_TOP|DT_SINGLELINE); // Draw out the caption
dc.SetTextColor(crOldColor);
}
if ( (state & ODS_FOCUS ) ) // If the button is focused
{
int iChange = 3;
rt.top += iChange;
rt.left += iChange;
rt.right -= iChange;
rt.bottom -= iChange;
dc.DrawFocusRect(rt);
}
dc.Detach();
}
BOOL CButtonDialer::OnEraseBkgnd(CDC* pDC)
{
CRect rect;
GetClientRect(&rect);
//255,255,255
CBrush myBrush(RGB(173, 41, 41)); // dialog background color
CBrush *pOld = pDC->SelectObject(&myBrush);
BOOL bRes = pDC->PatBlt(0, 0, rect.Width(), rect.Height(), PATCOPY);
pDC->SelectObject(pOld); // restore old brush
return bRes; // CDialog::OnEraseBkgnd(pDC);
}
You need to provide a message handler for the WM_ERASEBKGND message and paint the background yourself.
Put a normal button on the Resource Editor.
On the .h file of the form where you use it, declare a CMFCButton variable like m_btnRead.
In the DoDataExchange method of your form append a line
DDX_Control(pDX, IDC_BUTTON_READ, m_btnRead);
On the method where you initialize your form (OnInitDialog, Create, etc.) append a line
m_btnRead.SetFaceColor(RGB(0, 255, 255));
and now you are done!

How to get extra data from MFC Tab Control (TabCtrl)?

I have created an MFC dialog based application to study tab control. In a tab control it is possible to set application specific data to each tab.
I am trying to understand how to set/retrieve the data for individual tabs of the tab control.
Here is a sample application I am creating. Each tab of the control is supposed to store some GPU info.
As I understand, there are 3 steps to add application specific data.
Create a user defined structure, whose 1st member should be of type TCITEMHEADER.
struct GPU {
std::wstring name;
int busid;
};
struct tabData {
TCITEMHEADER tabItemHeader;
GPU gpu;
};
Tell the tab control about the extra bytes, the user defined structure is going to take. This I am doing in DoDataExchange().
int extraBytes = sizeof(tabData) - sizeof(TCITEMHEADER);
auto status = tabCtrl1.SetItemExtra(extraBytes);
Set user defined data while adding tabs.
static int tabCtr = 0;
tabData td;
td.tabItemHeader.pszText = _T("TabX");
td.tabItemHeader.mask = TCIF_TEXT;
td.gpu.name = L"AMD NVIDIA";
td.gpu.busid = 101;
TabCtrl_InsertItem(tabCtrl1.GetSafeHwnd(), tabCtr, &td);
Now to get the data, we simply have to call TabCtrl_GetItem().
tabData td2;
td2.tabItemHeader.pszText = new TCHAR[20];
td2.tabItemHeader.cchTextMax = 20;
td2.tabItemHeader.mask = TCIF_TEXT;
td2.gpu.busid = 0;
TabCtrl_GetItem(tabCtrl1.GetSafeHwnd(), 0, &td2);
But as we can see in the following image. I do get the tab text (pszText member - data Item 1 in image), but not the extra data that I had associated with it previously (Data Items 2 and 3 in image).
Which step am I missing?
Why is the structure associated with application defined data not getting populated?
Additional Info
Here is the complete code for the application.
CPP File:
// tabCtrlStackOverflowDlg.cpp : implementation file
//
#include "stdafx.h"
#include "tabCtrlStackOverflow.h"
#include "tabCtrlStackOverflowDlg.h"
#include "afxdialogex.h"
#include <string>
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
struct GPU {
std::wstring name;
int busid;
};
struct tabData
{
TCITEMHEADER tabItemHeader;
GPU gpu;
};
CtabCtrlStackOverflowDlg::CtabCtrlStackOverflowDlg(CWnd* pParent /*=NULL*/)
: CDialogEx(IDD_TABCTRLSTACKOVERFLOW_DIALOG, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}
void CtabCtrlStackOverflowDlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
DDX_Control(pDX, IDC_TAB1, tabCtrl1);
int extraBytes = sizeof(tabData) - sizeof(TCITEMHEADER);
auto status = tabCtrl1.SetItemExtra(extraBytes);
wchar_t *t = status ? L"SetItemExtra() success" : L"SetItemExtra() fail";
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(t);
}
BEGIN_MESSAGE_MAP(CtabCtrlStackOverflowDlg, CDialogEx)
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
ON_BN_CLICKED(IDADDTAB, &CtabCtrlStackOverflowDlg::OnBnClickedAddtab)
ON_BN_CLICKED(IDC_GETITEM0, &CtabCtrlStackOverflowDlg::OnBnClickedGetitem0)
ON_BN_CLICKED(IDCLOSE, &CtabCtrlStackOverflowDlg::OnBnClickedClose)
END_MESSAGE_MAP()
// CtabCtrlStackOverflowDlg message handlers
BOOL CtabCtrlStackOverflowDlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CtabCtrlStackOverflowDlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CtabCtrlStackOverflowDlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
void CtabCtrlStackOverflowDlg::OnBnClickedAddtab()
{
static int tabCtr = 0;
tabData td;
td.tabItemHeader.pszText = _T("TabX");
td.tabItemHeader.mask = TCIF_TEXT;
td.gpu.name = L"AMD NVIDIA";
td.gpu.busid = 101;
int status = TabCtrl_InsertItem(tabCtrl1.GetSafeHwnd(), tabCtr, &td);
wchar_t *t = L"";
if (status == -1)
{
t = L"TabCtrl_InsertItem() Fail";
}
else
{
t = L"TabCtrl_InsertItem() success";
}
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(t);
tabCtr++;
}
void CtabCtrlStackOverflowDlg::OnBnClickedGetitem0()
{
tabData td2;
td2.tabItemHeader.pszText = new TCHAR[20];
td2.tabItemHeader.cchTextMax = 20;
td2.tabItemHeader.mask = TCIF_TEXT;
td2.gpu.busid = 0;
if (TabCtrl_GetItem(tabCtrl1.GetSafeHwnd(), 0, &td2) == TRUE)
{
std::wstring text = td2.tabItemHeader.pszText;
text += std::wstring(L" ") + td2.gpu.name;
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(text.c_str());
}
else
{
GetDlgItem(IDC_STATUSTEXT)->SetWindowTextW(_T("TabCtrl_GetItem()
error"));
}
}
void CtabCtrlStackOverflowDlg::OnBnClickedClose()
{
CDialog::OnCancel();
}
Header File:
// tabCtrlStackOverflowDlg.h : header file
//
#pragma once
#include "afxcmn.h"
// CtabCtrlStackOverflowDlg dialog
class CtabCtrlStackOverflowDlg : public CDialogEx
{
// Construction
public:
CtabCtrlStackOverflowDlg(CWnd* pParent = NULL); // standard constructor
// Dialog Data
#ifdef AFX_DESIGN_TIME
enum { IDD = IDD_TABCTRLSTACKOVERFLOW_DIALOG };
#endif
protected:
virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support
// Implementation
protected:
HICON m_hIcon;
// Generated message map functions
virtual BOOL OnInitDialog();
afx_msg void OnPaint();
afx_msg HCURSOR OnQueryDragIcon();
DECLARE_MESSAGE_MAP()
public:
CTabCtrl tabCtrl1;
afx_msg void OnBnClickedAddtab();
afx_msg void OnBnClickedGetitem0();
afx_msg void OnBnClickedClose();
};
Solution Summary
From Barmak Shemirani's answer here are the 3 reasons my code wasn't working. Must read his answer for better understanding.
TCIF_PARAM must be set in mask, while doing TCM_INSERTITEM, and TCM_GETITEM.
I was using local variables created on stack (tabData td2; object). The reference to this variable was becoming invalid as soon as it was going out of scope.
Using std::wstring in the structure being used for TCM_INSERTITEM. It is better to use data types whose size can be accurately be determined (like plain old data types.).
As Barmak Shemirani points out in comments, the documentation for TCITEMHEADER is scarce. His answer provides a thorough explanation.
Conflict with documentation
Documentation for TCITEMHEADER does not mention using TCIF_PARAM flag. Maybe that's a mistake in documention!
It's better if SetItemExtra is moved to OnInitDialog after default procedure is called. This ensures SetItemExtra is called only once when control is empty.
The structure GPU has a std::wstring member whose data size is unknown at the start. TCM_INSERTITEM cannot make a copy of this data unless you have a simple POD structure.
To store the data in the tab, replace std::wstring with wchar_t name[100] so that data is a simple POD structure with fixed size.
struct GPU
{
//std::wstring name;
wchar_t name[100];
int busid;
};
struct tabData
{
TCITEMHEADER tabItemHeader;
GPU gpu;
};
void CMyDialog::OnBnClickedAddtab()
{
int index = tab.GetItemCount();
wchar_t tabname[50];
wsprintf(tabname, L"Tab %d", index);
tabData sdata = { 0 };
sdata.tabItemHeader.mask = TCIF_TEXT | TCIF_PARAM;
sdata.tabItemHeader.pszText = tabname;
wsprintf(sdata.gpu.name, L"AMD NVIDIA %d", index);
sdata.gpu.busid = 101;
tab.SendMessage(TCM_INSERTITEM, index, (LPARAM)(TCITEMHEADER*)(&sdata));
}
void CMyDialog::OnBnClickedGetitem0()
{
int index = tab.GetCurSel();
tabData data = { 0 };
wchar_t buf[20] = { 0 };
data.tabItemHeader.pszText = buf;
data.tabItemHeader.cchTextMax = sizeof(buf)/sizeof(wchar_t);
data.tabItemHeader.mask = TCIF_TEXT | TCIF_PARAM;
if(tab.SendMessage(TCM_GETITEM, index, (LPARAM)(TCITEMHEADER*)(&data)))
{
CString str;
str.Format(L"%d %s", data.gpu.busid, data.gpu.name);
GetDlgItem(IDC_STATIC1)->SetWindowText(str);
}
}
Alternative method:
If std::wstring name; cannot be replaced with wchar_t buffer, we have to define a separate permanent data, for example using std::vector. Then we use the lParam value in TCITEM to point to the vector.
This method only needs the standard 4 bytes of lParam, it doesn't require TCITEMHEADER and SetItemExtra. You can even define std::vector<GPU>. Example:
std::vector<tabData> m_data;
BOOL CMyDialog::OnInitDialog()
{
CDialogEx::OnInitDialog();
tabData data;
data.gpu.name = L"AMD NVIDIA1";
data.gpu.busid = 101;
m_data.push_back(data);
data.gpu.name = L"AMD NVIDIA2";
data.gpu.busid = 102;
m_data.push_back(data);
return TRUE;
}
void CMyDialog::OnBnClickedAddtab()
{
static int tabCtr = 0;
if(tabCtr >= (int)m_data.size())
return;
TCITEM item = { 0 };
item.pszText = _T("TabX");
item.mask = TCIF_TEXT | TCIF_PARAM;
item.lParam = (LPARAM)&m_data[tabCtr];
tab.InsertItem(tabCtr, &item);
tabCtr++;
}
void CMyDialog::OnBnClickedGetitem0()
{
TCITEM item = { 0 };
item.mask = TCIF_TEXT | TCIF_PARAM;
if(tab.GetItem(tab.GetCurSel(), &item) == TRUE)
{
tabData* ptr = (tabData*)item.lParam;
CString str;
str.Format(L"%d %s", ptr->gpu.busid, ptr->gpu.name.c_str());
GetDlgItem(IDC_STATIC1)->SetWindowText(str);
}
}

error C2664: 'int LSexecuteScriptLng(void *,const char *)

// Salam001Dlg.cpp : implementation file
//
#include "stdafx.h"
#include "Salam001.h"
#include "Salam001Dlg.h"
#include "DlgProxy.h"
#include "afxdialogex.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif
// CSalam001Dlg dialog
IMPLEMENT_DYNAMIC(CSalam001Dlg, CDialogEx);
CSalam001Dlg::CSalam001Dlg(CWnd* pParent /*=NULL*/)
: CDialogEx(CSalam001Dlg::IDD, pParent)
{
m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);
m_pAutoProxy = NULL;
}
CSalam001Dlg::~CSalam001Dlg()
{
// If there is an automation proxy for this dialog, set
// its back pointer to this dialog to NULL, so it knows
// the dialog has been deleted.
if (m_pAutoProxy != NULL)
m_pAutoProxy->m_pDialog = NULL;
}
void CSalam001Dlg::DoDataExchange(CDataExchange* pDX)
{
CDialogEx::DoDataExchange(pDX);
}
BEGIN_MESSAGE_MAP(CSalam001Dlg, CDialogEx)
ON_WM_CLOSE()
ON_WM_PAINT()
ON_WM_QUERYDRAGICON()
END_MESSAGE_MAP()
// CSalam001Dlg message handlers
BOOL CSalam001Dlg::OnInitDialog()
{
CDialogEx::OnInitDialog();
// Set the icon for this dialog. The framework does this automatically
// when the application's main window is not a dialog
SetIcon(m_hIcon, TRUE); // Set big icon
SetIcon(m_hIcon, FALSE); // Set small icon
// TODO: Add extra initialization here
return TRUE; // return TRUE unless you set the focus to a control
}
// If you add a minimize button to your dialog, you will need the code below
// to draw the icon. For MFC applications using the document/view model,
// this is automatically done for you by the framework.
void CSalam001Dlg::OnPaint()
{
if (IsIconic())
{
CPaintDC dc(this); // device context for painting
SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);
// Center icon in client rectangle
int cxIcon = GetSystemMetrics(SM_CXICON);
int cyIcon = GetSystemMetrics(SM_CYICON);
CRect rect;
GetClientRect(&rect);
int x = (rect.Width() - cxIcon + 1) / 2;
int y = (rect.Height() - cyIcon + 1) / 2;
// Draw the icon
dc.DrawIcon(x, y, m_hIcon);
}
else
{
CDialogEx::OnPaint();
}
}
// The system calls this function to obtain the cursor to display while the user drags
// the minimized window.
HCURSOR CSalam001Dlg::OnQueryDragIcon()
{
return static_cast<HCURSOR>(m_hIcon);
}
// Automation servers should not exit when a user closes the UI
// if a controller still holds on to one of its objects. These
// message handlers make sure that if the proxy is still in use,
// then the UI is hidden but the dialog remains around if it
// is dismissed.
void CSalam001Dlg::OnClose()
{
if (CanExit())
CDialogEx::OnClose();
}
void CSalam001Dlg::OnOK()
{//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int nError, nPointersNow;
double dStatus, dn_Mu, dSol_Inv, dSol_Rot;
CString csScript, cs;
// Get user's staffing requirements from our dialog box
//UpdateData();
// Load staffing requirements into the LINGO transfer array.
// LINGO uses double precision for all values.
dn_Mu = 5.0;
//n_Mu[0] = (double)n_Mu;
// create the LINGO environment object
pLSenvLINGO pLINGO;
pLINGO = LScreateEnvLng();
if (!pLINGO)
{
AfxMessageBox(_T("Unable to create LINGO Environment"));
return;
}
// Open LINGO's log file
nError = LSopenLogFileLng(pLINGO, "C:\\LINGO8\\LINGO.log");
if (nError) goto ErrorExit;
// Pass memory transfer pointers to LINGO
// #POINTER(1)
nError = LSsetPointerLng(pLINGO, &dn_Mu, &nPointersNow);
if (nError) goto ErrorExit;
// #POINTER(2)
nError = LSsetPointerLng(pLINGO, &dSol_Inv, &nPointersNow);
if (nError) goto ErrorExit;
// #POINTER(3)
/* nError = LSsetPointerLng(pLINGO, &dSol_Rot, &nPointersNow);
if (nError) goto ErrorExit;
*/
// #POINTER(3)
nError = LSsetPointerLng(pLINGO, &dStatus, &nPointersNow);
if (nError) goto ErrorExit;
// Here is the script we want LINGO to run
csScript = L"SET ECHOIN 1\n";
csScript = csScript + L"TAKE \\Salam002\\LINGO1-3.LNG\n" ;
csScript = csScript + L"GO\n";
csScript = csScript + L"QUIT\n";
// Run the script
dStatus = -1.e0;
nError = LSexecuteScriptLng(pLINGO, ( LPCTSTR ) csScript);
// Close the log file
LScloseLogFileLng(pLINGO);
// Any problems?
if (nError || dStatus)
{
// Had a problem
AfxMessageBox( _T("Unable to solve!"));
}
else {
// Everything went ok ... load results into the dialog box
// m_csStartMon.Format("%d", (int)dStart[0]);
UpdateData(FALSE);
}
goto Exit;
ErrorExit:
cs.Format(_T("LINGO Errorcode: %d"), nError);
AfxMessageBox(cs);
return;
Exit:
LSdeleteEnvLng(pLINGO);
/////////////////////////////////////////////////////////////////////////////////////////////////////////
}
void CSalam001Dlg::OnCancel()
{
if (CanExit())
CDialogEx::OnCancel();
}
BOOL CSalam001Dlg::CanExit()
{
// If the proxy object is still around, then the automation
// controller is still holding on to this application. Leave
// the dialog around, but hide its UI.
if (m_pAutoProxy != NULL)
{
ShowWindow(SW_HIDE);
return FALSE;
}
return TRUE;
}
I need help to fix the problem in the following line :
nError = LSexecuteScriptLng(pLINGO, ( LPCTSTR ) csScript);
the error message is :
error C2664: 'int LSexecuteScriptLng(void *,const char )' : cannot
convert argument 2 from 'LPCTSTR' to 'const char
Please help me.
It simply means what is says: you cannot convert a 2-byte-character to a one-byte character. You need to declare and use all of char variables. Since your project settings are set to Unicode, TCHAR would map to char, and also CString would map to CStringW. You have options:
Declare all needed variables to be char (or derivation of char, for example CStringA)
(Not advised) is to change project settings to use Multi-byte.
DON'T ever forcefully type cast it. It like forcing a float* to and int* - wont work!
See this article
The function shown in your error message is documented in the LINGO DLL functions section of their help documentation. The function
"int LSexecuteScriptLng( pLSenvLINGO pL, char* pcScript)"
takes 2 arguments, with the second one being a pointer to a character string. You should define your character string with something like:
char csScript[256];
Then use it in your Lingo function:
nError = LSexecuteScriptLng(pLINGO, csScript);

I am having trouble getting my d3d window to build in VS 2013

OK so here is my source code this is from a tutorial i found online in creating your first DX window. so i copied it by typing it out to try and remember better. Anyways the problem i am having is that I cannot get the program to build in VS, I have tried changing the Linker subsystem to windows, didnt work.
ERROR Recieved
1>MSVCRTD.lib(crtexew.obj) : error LNK2019: unresolved external symbol _WinMain#16 referenced in function ___tmainCRTStartup
1>e:\documents\visual studio 2013\Projects\Project1\Debug\Project1.exe : fatal error LNK1120: 1 unresolved externals
Heres external link to code https://gist.github.com/bANNji/24ebedaf5a72f2003d29
//include the basic windows header files and the Direct3dD Header file
#include <windows.h>
#include <windowsx.h>
#include <d3d9.h>
// Include the DIrect3D library file
#pragma comment (lib, "d3d9.lib")
// global declarations
LPDIRECT3D9 d3d; // The pointer to our Direct3D Interface
LPDIRECT3DDEVICE9 d3ddev; // the pointer to the device class
// functiuon prototypes
void initD3D(HWND hWnd); // Sets up and initializes Direct3D
void render_frame(void); // Renders a single frame
void cleanD3D(void); // Closes Direct3D and releases memory
// The window proc function prototype
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
// this function initializes and prepares direct3d for use
void initD3D(HWND hWnd)
{
d3d = Direct3DCreate9(D3D_SDK_VERSION); // Create the Direct3D Interface
D3DPRESENT_PARAMETERS d3dpp; // create a stuct to hold verious device information
ZeroMemory(&d3dpp, sizeof(d3dpp)); //Clear out the stuct for usee
d3dpp.Windowed = TRUE; // Program windowed not full screen
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; // Discard old frames
d3dpp.hDeviceWindow = hWnd; // Set the window to be used by Direct3D
// Create a deviced calss using this information and information from the d3dpp stuct
d3d->CreateDevice(D3DADAPTER_DEFAULT,
D3DDEVTYPE_HAL,
hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,
&d3ddev);
}
// THE FUN STUFF
// this is the function used to render a single frame
void render_frame(void)
{
// clear the window to a deep blue
d3ddev->Clear(0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(0, 40, 100), 1.0f, 0);
d3ddev->BeginScene(); // this begins the 3D Scene
// do 3D Rendering on the back buffer here...
d3ddev->EndScene(); // ends the 3D Scene
d3ddev->Present(NULL, NULL, NULL, NULL); // This displays the created frame
}
// THis is the function that cleans up Direct3D and COM
void cleanD3D(void)
{
d3ddev->Release(); // close and release the 3D Device
d3d->Release(); //Close and release Direct3D
}
The error means exactly what it says: You don't have a WinMain. I would strongly suggest you first learn how to wield the Win32 API to create and manipulate windows by themselves before you try to use them with Direct3D. It is heavily documented on MSDN and pretty easy to grasp. Here's a quick jumble of sample code (incomplete, obviously) to help give you a reference point to get started:
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HRESULT hr = CoInitializeEx(NULL,COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE);
WNDCLASSEX wndClass;
ZeroMemory(&wndClass,sizeof(wndClass));
wndClass.cbSize = sizeof(wndClass);
wndClass.cbClsExtra = 0;
wndClass.cbWndExtra = 0;
wndClass.hbrBackground = NULL;
wndClass.hCursor = LoadCursor(hInstance,LoadCursor(NULL,IDC_ARROW);
wndClass.hIcon = LoadIcon(hInstance,LoadIcon(NULL,IDI_APPLICATION);
wndClass.hIconSm = LoadIcon(hInstance,LoadIcon(NULL,IDI_APPLICATION);
wndClass.hInstance = hInstance;
wndClass.lpszMenuName = NULL;
wndClass.lpfnWndProc = winProc;
wndClass.lpszClassName = "derp";
wndClass.style = CS_DBLCLKS | CS_OWNDC | CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&wndClass);
RECT win = {0,0,width,height};
AdjustWindowRectEx(&win,flags,FALSE,WS_EX_APPWINDOW);
int winWidth = win.right - win.left;
int winHeight = win.bottom - win.top;
hWnd = CreateWindowEx( WS_EX_APPWINDOW,
"derp",
"derpderp",
flags | WS_CLIPCHILDREN | WS_CLIPSIBLINGS,
GetSystemMetrics(SM_CXSCREEN)/2 - width/2,
GetSystemMetrics(SM_CYSCREEN)/2 - height/2,
winWidth,
winHeight,
HWND_DESKTOP,
NULL,
hInstance,
NULL
);
SetWindowPos( hWnd,
HWND_NOTOPMOST,
(GetSystemMetrics(SM_CXSCREEN)/2) - (winWidth/2),
(GetSystemMetrics(SM_CYSCREEN)/2) - (winHeight/2),
winWidth,
winHeight,
SWP_SHOWWINDOW
);
ShowWindow(hWnd,nCmdShow);
UpdateWindow(hWnd);
/* Do your other stuff here */
return 0;
}
And the winproc definition:
LRESULT CALLBACK App::WinProc( HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam )
{
switch(uMsg)
{
// NOTE: Obviously you'd need only those that matter to you, and you'd need to fill them in
case WM_KEYUP:
case WM_KEYDOWN:
case WM_CHAR:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONDBLCLK:
case WM_RBUTTONUP:
case WM_MOUSEMOVE:
case WM_SYSKEYDOWN:
case WM_MOUSEWHEEL:
case WM_ACTIVATE:
case WM_SYSKEYUP:
case WM_SYSCOMMAND:
case WM_CREATE:
case WM_CLOSE:
case WM_DESTROY:
App::GetInstance()->Shutdown();
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd,uMsg,wParam,lParam);
}
return 0;
}

Resources