how to read text file and show it on edit control in win 32 unicode character set? - visual-c++

i have been making a program to read the text from a text file on a button click and show it on the edit control. when the button is clicked, the dialog box opens to select the text file and clicking on ok, it should display on edit control but i am not getting the text in proper format.
this is the output : output image from visual studio
#include <windows.h>
const wchar_t g_szClassName[] = { L"myWindowClass" };
#define IDC_MAIN_EDIT 101
#define IDC_MAIN_BUTTON 102
#define IDC_MAIN_BUTTON1 103
BOOL LoadTextFileToEdit(HWND hEdit, LPTSTR pszFileName)
{
HANDLE hFile;
BOOL bSuccess = FALSE;
hFile = CreateFile(pszFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
OPEN_EXISTING, 0, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
DWORD dwFileSize;
dwFileSize = GetFileSize(hFile, NULL);
if (dwFileSize != 0xFFFFFFFF)
{
wchar_t* pszFileText;
pszFileText = (wchar_t*)GlobalAlloc(GPTR, dwFileSize + 1);
if (pszFileText != NULL)
{
DWORD dwRead;
if (ReadFile(hFile, (LPVOID)pszFileText, dwFileSize, &dwRead, NULL))
{
pszFileText[dwFileSize] = 0 ; // Add null terminator
if (SetWindowText(hEdit, (LPCWSTR)pszFileText))
bSuccess = TRUE; // It worked!
}
GlobalFree(pszFileText);
}
}
CloseHandle(hFile);
}
return bSuccess;
}
// Step 4: the Window Procedure
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_CREATE:
{
HFONT hfont;
HWND hedit,button,btnsave;
hedit = CreateWindowEx(WS_EX_CLIENTEDGE, L"EDIT", L"My Own Window", WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL | ES_AUTOVSCROLL | ES_MULTILINE
, CW_USEDEFAULT, CW_USEDEFAULT, 100, 100, hwnd, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL);
button = CreateWindowEx(WS_EX_CLIENTEDGE, L"BUTTON", L"Open File", WS_CHILD | WS_VISIBLE|WS_BORDER|WS_TABSTOP
,CW_USEDEFAULT, CW_USEDEFAULT, 50, 20, hwnd, (HMENU)IDC_MAIN_BUTTON, GetModuleHandle(NULL), NULL);
btnsave = CreateWindowEx(WS_EX_CLIENTEDGE, L"BUTTON", L"Save File", WS_CHILD | WS_VISIBLE | WS_EX_STATICEDGE|WS_TABSTOP
, CW_USEDEFAULT, CW_USEDEFAULT, 50, 20, hwnd, (HMENU)IDC_MAIN_BUTTON1, GetModuleHandle(NULL), NULL);
if (hedit == NULL)
{
MessageBox(NULL, L"Could not create edit box", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
hfont = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
SendMessage(hedit, WM_SETFONT, (WPARAM)hfont, MAKELPARAM(FALSE, 0));
//SetWindowText(button, L"Open File");
//SetWindowText(btnsave, L"Save File");
}
break;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_MAIN_BUTTON:
{
OPENFILENAME ofn;
wchar_t szFileName[MAX_PATH] = L"";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn); // SEE NOTE BELOW
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST | OFN_HIDEREADONLY;
ofn.lpstrDefExt = L"txt";
if (GetOpenFileName(&ofn))
{
// Do something usefull with the filename stored in szFileName
HWND hedit;
hedit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
LoadTextFileToEdit(hedit, szFileName);
}
}
break;
case IDC_MAIN_BUTTON1:
{
OPENFILENAME ofn;
wchar_t szFileName[MAX_PATH] = L"";
ZeroMemory(&ofn, sizeof(ofn));
ofn.lStructSize = sizeof(ofn); // SEE NOTE BELOW
ofn.hwndOwner = hwnd;
ofn.lpstrFilter = L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0";
ofn.lpstrFile = szFileName;
ofn.nMaxFile = MAX_PATH;
ofn.Flags = OFN_EXPLORER | OFN_PATHMUSTEXIST | OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT;
ofn.lpstrDefExt = L"txt";
if (GetOpenFileName(&ofn))
{
// Do something usefull with the filename stored in szFileName
HWND hedit;
hedit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
}
}
break;
default:
break;
}
break;
case WM_SIZE:
{
HWND hEdit,button,btnsave;
RECT rcClient;
GetClientRect(hwnd, &rcClient);
hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
button = GetDlgItem(hwnd, IDC_MAIN_BUTTON);
btnsave = GetDlgItem(hwnd, IDC_MAIN_BUTTON1);
SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom-120, SWP_NOZORDER);
SetWindowPos(button, NULL, rcClient.right-200, rcClient.bottom-30, 70, 30, SWP_NOZORDER);
SetWindowPos(btnsave, NULL, rcClient.right - 100, rcClient.bottom - 30, 70, 30, SWP_NOZORDER);
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, msg, wParam, lParam);
}
return 0;
}
int WINAPI WinMain(HINSTANCE hinstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
WNDCLASSEX wc;
HWND hwnd;
MSG msg;
//step 1: registering the window class
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = 0;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hinstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
wc.lpszMenuName = NULL;
wc.lpszClassName = g_szClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
{
MessageBox(NULL, L"Window Registration failed", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
//step 2: Creating the Window
hwnd = CreateWindowEx(WS_EX_CLIENTEDGE,
g_szClassName, L"The title of my window", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 500, 300,
NULL, NULL, hinstance, NULL);
if (hwnd == NULL)
{
MessageBox(NULL, L"Window Registration failed", L"Error!", MB_ICONEXCLAMATION | MB_OK);
return 0;
}
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
//Step-3: the message loop
while (GetMessage(&msg, NULL, 0, 0)>0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}

i got the answer to my question. Actually in unicode wide string a character is of 2 bytes so we need to allocate twice the memory. so replace :
pszFileText = (wchar_t*)GlobalAlloc(GPTR, dwFileSize + 1);
with
pszFileText = (wchar_t*)GlobalAlloc(GPTR, 2*(dwFileSize + 1));
and
if (ReadFile(hFile, (LPVOID)pszFileText, dwFileSize, &dwRead, NULL))
with
if (ReadFile(hFile, (LPVOID)pszFileText, 2*(dwFileSize+1), &dwRead, NULL))

Related

CMFCEditBrowseCtrl is cropping the file name

I select an image using the CMFCEditBrowseCtrl which has the name:
D:\WhatsApp Image 2020-04-02 at 13.03.48.jpeg
So it is now selected in the control:
Now, I decide to hit the Browse button again:
See?
D:\WhatsApp Image 2020-04-02 at 13.03.48.jpeg appears to be truncated to to at 13.03.48.jpeg. But the moment I click the mouse into the filename control it then shows correct:
It doesn't always show the full name again if you click the edit box. But guaranteed, if you click OK it will be correct and complete.
This is going to be confusing for the user.
Update 1
If I click in the filename and click the HOME button on the keyboard then the rest of the file name comes into view.
Update 2
I have delved into the MFC source code for this bit and this is what it looks like:
case BrowseMode_File:
{
CString strFile;
GetWindowText(strFile);
if (!strFile.IsEmpty())
{
TCHAR fname [_MAX_FNAME];
_tsplitpath_s(strFile, NULL, 0, NULL, 0, fname, _MAX_FNAME, NULL, 0);
CString strFileName = fname;
strFileName.TrimLeft();
strFileName.TrimRight();
if (strFileName.IsEmpty())
{
strFile.Empty();
}
const CString strInvalidChars = _T("*?<>|");
if (strFile.FindOneOf(strInvalidChars) >= 0)
{
if (!OnIllegalFileName(strFile))
{
SetFocus();
return;
}
}
}
CFileDialog dlg(TRUE, !m_strDefFileExt.IsEmpty() ? (LPCTSTR)m_strDefFileExt : (LPCTSTR)NULL, strFile, m_dwFileDialogFlags, !m_strFileFilter.IsEmpty() ? (LPCTSTR)m_strFileFilter : (LPCTSTR)NULL, NULL);
if (dlg.DoModal() == IDOK && strFile != dlg.GetPathName())
{
SetWindowText(dlg.GetPathName());
SetModify(TRUE);
OnAfterUpdate();
}
if (GetParent() != NULL)
{
GetParent()->RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
}
break;
}
Update 3
I have tried to roll out my own class that overrides the OnBrowse handler. It has improved logic for setting the default filter index and default file extension:
#include "stdafx.h"
#include "MyMFCEditBrowseFileCtrl.h"
IMPLEMENT_DYNAMIC(CMyMFCEditBrowseFileCtrl, CMFCEditBrowseCtrl)
BEGIN_MESSAGE_MAP(CMyMFCEditBrowseFileCtrl, CMFCEditBrowseCtrl)
END_MESSAGE_MAP()
void CMyMFCEditBrowseFileCtrl::OnBrowse()
{
CString strFile, strFileExtension;
GetWindowText(strFile);
if (!strFile.IsEmpty())
{
TCHAR fname[_MAX_FNAME];
TCHAR ext[_MAX_EXT];
_tsplitpath_s(strFile, NULL, 0, NULL, 0, fname, _MAX_FNAME, ext, _MAX_EXT);
CString strFileName = fname;
strFileName.TrimLeft();
strFileName.TrimRight();
if (strFileName.IsEmpty())
{
strFile.Empty();
}
strFileExtension = ext;
strFileExtension.Trim();
strFileExtension.MakeLower();
const CString strInvalidChars = _T("*?<>|");
if (strFile.FindOneOf(strInvalidChars) >= 0)
{
if (!OnIllegalFileName(strFile))
{
SetFocus();
return;
}
}
}
int iFilterIndex = 2; // jpg - fallback
m_strDefFileExt = _T("jpg");
if (strFileExtension == _T(".gif"))
{
iFilterIndex = 1;
m_strDefFileExt = _T("gif");
}
else if (strFileExtension == _T(".jpeg") || strFileExtension == _T(".jpg"))
{
iFilterIndex = 2;
m_strDefFileExt = _T("jpg");
}
else if (strFileExtension == _T(".png"))
{
iFilterIndex = 3;
m_strDefFileExt = _T("png");
}
else if (strFileExtension == _T(".tif") || strFileExtension == _T(".tiff"))
{
iFilterIndex = 4;
m_strDefFileExt = _T("tif");
}
else if (strFileExtension == _T(".bmp"))
{
iFilterIndex = 5;
m_strDefFileExt = _T("bmp");
}
CFileDialog dlg(TRUE, (LPCTSTR)m_strDefFileExt,
strFile,
m_dwFileDialogFlags,
!m_strFileFilter.IsEmpty() ? (LPCTSTR)m_strFileFilter : (LPCTSTR)NULL, NULL);
dlg.m_pOFN->nFilterIndex = iFilterIndex;
if (dlg.DoModal() == IDOK && strFile != dlg.GetPathName())
{
SetWindowText(dlg.GetPathName());
SetModify(TRUE);
OnAfterUpdate();
}
if (GetParent() != NULL)
{
GetParent()->RedrawWindow(NULL, NULL, RDW_FRAME | RDW_INVALIDATE | RDW_ALLCHILDREN);
}
}
But, it still have this odd behaviour I described.
Update 4
This issue is technically related to CFileDialog. If I simply try:
CFileDialog dlgOpen(TRUE, _T("MWB"), _T("123456789abcdefghijklmnopqrstuvwxyz.mwb"), OFN_PATHMUSTEXIST | OFN_HIDEREADONLY, strFilter, this);
Then all that is visibly selected is "rstuvwxyz.mwb".
Update 5
One of the replies here states:
This really isn't an MFC issue. The bad actor is the shell's COM object that implements the IFileDialog interface that is used by MFC under the hood. The following minimal example reproduces the problem using COM without any MFC code.
#include <Windows.h>
#include <ShlObj.h>
int WINAPI wWinMain(HINSTANCE hInst, HINSTANCE hPrevious, LPWSTR szCommandline, INT nShow)
{
HRESULT hr = CoInitialize(nullptr);
if (SUCCEEDED(hr))
{
IFileDialog *pfd = nullptr;
hr = CoCreateInstance(CLSID_FileOpenDialog,
nullptr,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pfd));
if (SUCCEEDED(hr))
{
COMDLG_FILTERSPEC rgFileSpec[] = {
{L"MWB Files (*.mwb)", L"*.mwb"},
{L"All Files (*.*)", L"*.*"}
};
hr = pfd->SetFileTypes(ARRAYSIZE(rgFileSpec), rgFileSpec);
hr = pfd->SetFileName(L"123456789abcdefghijklmnopqrstuvwxyz.mwb");
hr = pfd->Show(NULL);
pfd->Release();
}
}
CoUninitialize();
return 0;
}
This class solves it
FileDialogHack.h:
#pragma once
#include <afxdlgs.h>
/////////////////////////////////////////////////////////////////////////////
// CFileDialogHack dialog
//
// solves bug in filedialog:
// https://developercommunity.visualstudio.com/t/problem-with-using-the-cfiledialog-class/1225634
//
class CFileDialogHack : public CFileDialog
{
public:
CFileDialogHack(BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL, LPCTSTR lpszFileName = NULL,
DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT,
LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL);
virtual INT_PTR DoModal();
protected:
HWINEVENTHOOK wineventhook();
public:
void _WinEventProcCallback(HWINEVENTHOOK hWinEventHook,
DWORD dwEvent, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread, DWORD dwmsEventTime);
LRESULT _CallWndProc(int code, WPARAM wParam, LPARAM lParam);
protected:
HWINEVENTHOOK m_hHook;
HHOOK m_hWndProcHook;
HWND m_hDialog;
HWND m_hCombo;
HWND m_hEdit;
BOOL m_bHook;
HWND m_hParent;
};
FileDialogHack.cpp:
#include "stdafx.h"
#include "FileDialogHack.h"
/////////////////////////////////////////////////////////////////////////////
// CMyFileDialogHack dialog
static CFileDialogHack* g_ptrfiledaloghack = nullptr;
CFileDialogHack::CFileDialogHack(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName,
DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd)
: CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd, 0, TRUE),
m_hHook(0), m_hWndProcHook(0), m_hParent(0), m_hDialog(0), m_hCombo(0), m_hEdit(0), m_bHook(0)
{
}
LRESULT CFileDialogHack::_CallWndProc(int code, WPARAM wParam, LPARAM lParam)
{
PCWPRETSTRUCT data = (PCWPRETSTRUCT)lParam;
if (data->hwnd == m_hCombo && data->message == CBEM_GETEDITCONTROL)
{
m_hEdit = (HWND)data->lResult;
return CallNextHookEx(0, code, wParam, lParam);
}
if (m_bHook)
{
if (data->hwnd == m_hEdit && data->message == EM_SETSEL &&
data->wParam == 0 && data->lParam == -1)
::SendMessage(m_hEdit, EM_SETSEL, (WPARAM)0, (LPARAM)0);
else if (data->hwnd == m_hParent && data->message == WM_ENTERIDLE)
{
m_bHook = 0;
TCHAR text[MAX_PATH];
::GetWindowText(m_hEdit, text, MAX_PATH - 1);
auto len = _tcslen(text);
::SendMessage(m_hEdit, EM_SETSEL, (WPARAM)0, (LPARAM)0);
::SendMessage(m_hEdit, EM_SETSEL, (WPARAM)0, (LPARAM)len);
::SetFocus(m_hEdit);
}
}
return CallNextHookEx(0, code, wParam, lParam);
}
static LRESULT CALLBACK CallWndProc(int code, WPARAM wParam, LPARAM lParam)
{
if (g_ptrfiledaloghack)
return g_ptrfiledaloghack->_CallWndProc(code, wParam, lParam);
return CallNextHookEx(0, code, wParam, lParam);
}
VOID CALLBACK CFileDialogHack::_WinEventProcCallback(HWINEVENTHOOK /*hWinEventHook*/,
DWORD dwEvent, HWND hwnd, LONG idObject, LONG /*idChild*/,
DWORD /*dwEventThread*/, DWORD /*dwmsEventTime*/)
{
if (idObject == OBJID_WINDOW && dwEvent == EVENT_OBJECT_CREATE)
{
if (IsWindow(hwnd) && ::GetDlgCtrlID(hwnd) == 1148)
{
m_hCombo = hwnd; // We have the file dialog's filename combobox field.
m_hDialog = ::GetParent(hwnd);
m_hParent = ::GetParent(m_hDialog);
m_hEdit = (HWND) ::SendMessage(m_hCombo, CBEM_GETEDITCONTROL, 0, 0);
DWORD threadID = GetWindowThreadProcessId(m_hDialog, NULL);
// Hook messages to the file dialog.
m_hWndProcHook = SetWindowsHookEx(WH_CALLWNDPROCRET, CallWndProc, NULL, threadID);
}
}
}
static VOID CALLBACK WinEventProcCallback(HWINEVENTHOOK hWinEventHook,
DWORD dwEvent, HWND hwnd, LONG idObject, LONG idChild, DWORD dwEventThread,
DWORD dwmsEventTime)
{
if (g_ptrfiledaloghack)
g_ptrfiledaloghack->_WinEventProcCallback(hWinEventHook,
dwEvent, hwnd, idObject, idChild, dwEventThread, dwmsEventTime);
}
HWINEVENTHOOK CFileDialogHack::wineventhook()
{
// Hook creation of the Open File Dialog.
g_ptrfiledaloghack = this;
m_bHook = 1;
return SetWinEventHook(
EVENT_OBJECT_CREATE, EVENT_OBJECT_CREATE,
NULL, WinEventProcCallback, GetCurrentProcessId(), 0,
WINEVENT_OUTOFCONTEXT);
}
INT_PTR CFileDialogHack::DoModal()
{
m_hHook = wineventhook();
auto r = __super::DoModal();
UnhookWinEvent(m_hHook);
UnhookWindowsHookEx(m_hWndProcHook);
g_ptrfiledaloghack = nullptr;
return r;
}

Which thread is used in the same function of multithread

In mfc code,
Declare as follow
CWinThread* _pThread[5];
DWORD _ThreadArg[5] = { HIGHEST_THREAD, // 0x00
ABOVE_AVE_THREAD, // 0x3F
NORMAL_THREAD, // 0x7F
BELOW_AVE_THREAD, // 0xBF
LOWEST_THREAD // 0xFF
};
int i;
for (i= 0; i< 5; i++)
{
_pThread[i] = AfxBeginThread(ThreadFunc,
&_ThreadArg[i],
THREAD_PRIORITY_NORMAL,
0,
//CREATE_SUSPENDED,
NULL,
NULL);
//_pThread[i]->ResumeThread();
}
// setup relative priority of threads
_pThread[0]->SetThreadPriority(THREAD_PRIORITY_HIGHEST);
_pThread[1]->SetThreadPriority(THREAD_PRIORITY_ABOVE_NORMAL);
_pThread[2]->SetThreadPriority(THREAD_PRIORITY_NORMAL);
_pThread[3]->SetThreadPriority(THREAD_PRIORITY_BELOW_NORMAL);
_pThread[4]->SetThreadPriority(THREAD_PRIORITY_LOWEST);
use same thread function
UINT CThreadPoolDlg::ThreadFuncTh1(LPVOID ThreadArg)
{
DWORD dwArg = *(DWORD*)ThreadArg;
//txtTh[0].SetWindowTextW(_T("23"));
AfxGetMainWnd()->GetDlgItem(IDC_THD1)->SetWindowText(_T("1"));
return 0;
}
How do I check which thread is in use in same function?
I get a answer as follow
_pThread[0] = AfxBeginThread(ThreadFunc,this,
THREAD_PRIORITY_NORMAL,
0,
NULL,
NULL);
_pThread[1] = AfxBeginThread(ThreadFunc,this,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED,
NULL);
_pThread[2] = AfxBeginThread(ThreadFunc,this,
THREAD_PRIORITY_NORMAL,
0,
CREATE_SUSPENDED,
NULL);
the thread function is declare as follow
UINT CThreadPoolDlg::ThreadFunc(LPVOID ThreadArg)
{
CThreadPoolDlg* dwArg = (CThreadPoolDlg*)ThreadArg;
DWORD dThread = GetCurrentThreadId();
//txtTh[0].SetWindowTextW(_T("23"));
while(1)
{
CString strTemp;
if(dThread == dwArg->_pThread[0]->m_nThreadID)
{
AfxGetMainWnd()->GetDlgItem(IDC_THD1)->GetWindowText(strTemp);
int n = _wtoi(strTemp);
strTemp.Format(_T("%d"), ++n);
AfxGetMainWnd()->GetDlgItem(IDC_THD1)->SetWindowText(strTemp);
if(n > 5)
{
::SendMessage(dwArg->GetSafeHwnd(), OWM_MYMETHOD, 0, 0);
//dwArg->_pThread[1]->ResumeThread();
}
}
if(dThread == dwArg->_pThread[1]->m_nThreadID)
{
AfxGetMainWnd()->GetDlgItem(IDC_THD2)->GetWindowText(strTemp);
int n = _wtoi(strTemp);
strTemp.Format(_T("%d"), ++n);
AfxGetMainWnd()->GetDlgItem(IDC_THD2)->SetWindowText(strTemp);
if(n > 5)
{
dwArg->_pThread[2]->ResumeThread();
}
}
if(dThread == dwArg->_pThread[2]->m_nThreadID)
{
AfxGetMainWnd()->GetDlgItem(IDC_THD3)->GetWindowText(strTemp);
int n = _wtoi(strTemp);
strTemp.Format(_T("%d"), ++n);
AfxGetMainWnd()->GetDlgItem(IDC_THD3)->SetWindowText(strTemp);
}
Sleep(500);
}
return 0;
}
Just look at the
DWORD dThread = GetCurrentThreadId();
dThread == dwArg->_pThread[1]->m_nThreadID
then I will get current thread id...

How to Render TriangleList and LineList in same frame in dx11

How to Render TriangleList and LineList in same frame in dx11.
I tried to bind two sets of buffers to GPU.
Each buffer set contains one index_buffer and one vertices buffer.
And use ID3D11Device::DrawIndexed Function to Render the vertices.
I thought that to decide what polygon to render just simply call the ID3D11DeviceContext::IASetPrimitiveTopology function real-timely.
But it seems won't work.
There would be only one single line rendered.
How can I render both the triangle and the line in same frame ?
My code is based on dxsdk tutorials03 in" dx11 area".The code is as follows.I simply add a ray render class to render a line .
#pragma once
//RayRenderClass.h
#include<D3D11.h>
#include<D3DX11.h>
#include<D3DX10math.h>
struct PointClass
{
float _XYZ[3];
};
struct VertexClass
{
PointClass pts;
float nor[3];
float tex[3];
};
class RayRenderClass
{
public:
RayRenderClass();
~RayRenderClass();
HRESULT Initialize(ID3D11Device* device, ID3D11DeviceContext* context);
HRESULT Shutdown();
HRESULT Render(ID3D11Device* device, ID3D11DeviceContext* context);
HRESULT UpdateStartPosition(D3DXVECTOR3 st);
HRESULT UpdateEndPosition(D3DXVECTOR3 ed);
D3DXVECTOR3 GetStartPosition();
D3DXVECTOR3 GetEndPosition();
private:
ULONG indices[2];
VertexClass pts[2];
ID3D11Buffer* m_indexBuffer;
ID3D11Buffer* m_vertices;
};
#include "RayRenderClass.h"
//RayRenderClass.cpp
#define SAFE_RELEASE(x) if((x)){(x)->Release(); x= nullptr;}
RayRenderClass::RayRenderClass()
{
ZeroMemory(pts, sizeof(pts));
//start point
pts[0].pts._XYZ[0] = 0.0f;
pts[0].pts._XYZ[1] = 0.0f;
pts[0].pts._XYZ[2] = 0.0f;
//end point
pts[1].pts._XYZ[0] = 1.0f;
pts[1].pts._XYZ[1] = 0.0f;
pts[1].pts._XYZ[2] = 0.0f;
}
RayRenderClass::~RayRenderClass()
{
}
HRESULT RayRenderClass::Initialize(ID3D11Device* device, ID3D11DeviceContext* context)
{
HRESULT hr = E_FAIL;
D3D11_BUFFER_DESC verticesDesc;
D3D11_BUFFER_DESC indexDesc;
D3D11_SUBRESOURCE_DATA verticesData;
D3D11_SUBRESOURCE_DATA indexData;
ZeroMemory(&verticesDesc, sizeof(verticesDesc));
verticesDesc.Usage = D3D11_USAGE_DYNAMIC;
verticesDesc.ByteWidth = sizeof(VertexClass)* 2;
verticesDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
verticesDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
ZeroMemory(&verticesData, sizeof(verticesData));
verticesData.pSysMem = &pts[0].pts._XYZ[0];
hr = device->CreateBuffer(&verticesDesc, &verticesData, &m_vertices);
if (FAILED(hr))
return hr;
ZeroMemory(&indexDesc, sizeof(indexDesc));
indexDesc.Usage = D3D11_USAGE_DEFAULT;
indexDesc.ByteWidth = sizeof(ULONG)* 2;
indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
ZeroMemory(&indexData, sizeof(indexData));
indexData.pSysMem = indices;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;
hr = device->CreateBuffer(&indexDesc, &indexData, &m_indexBuffer);
if (FAILED(hr))
{
return hr;
}
return S_OK;
}
HRESULT RayRenderClass::Shutdown()
{
SAFE_RELEASE(m_vertices);
SAFE_RELEASE(m_indexBuffer);
return S_OK;
}
HRESULT RayRenderClass::UpdateStartPosition(D3DXVECTOR3 st)
{
HRESULT hr = E_FAIL;
pts[0].pts._XYZ[0] = st.x;
pts[0].pts._XYZ[1] = st.y;
pts[0].pts._XYZ[2] = st.z;
return hr;
}
HRESULT RayRenderClass::UpdateEndPosition(D3DXVECTOR3 ed)
{
HRESULT hr = E_FAIL;
pts[1].pts._XYZ[0] = ed.x;
pts[1].pts._XYZ[1] = ed.y;
pts[1].pts._XYZ[2] = ed.z;
return hr;
}
D3DXVECTOR3 RayRenderClass::GetStartPosition()
{
D3DXVECTOR3 ret = { pts[0].pts._XYZ };
return ret;
}
D3DXVECTOR3 RayRenderClass::GetEndPosition()
{
D3DXVECTOR3 ret = { pts[1].pts._XYZ };
return ret;
}
HRESULT RayRenderClass::Render(ID3D11Device* device, ID3D11DeviceContext* context)
{
HRESULT hr = E_FAIL;
D3D11_MAPPED_SUBRESOURCE mappedResource;
VertexClass* verticesPtr;
UINT stride = sizeof(VertexClass);
UINT offset = 0;
hr = context->Map(m_vertices, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
if (FAILED(hr))
return hr;
verticesPtr = (VertexClass*)mappedResource.pData;
memcpy(verticesPtr, (void*)pts, (sizeof(VertexClass)* 2));
context->Unmap(m_vertices, 0);
context->IASetVertexBuffers(0, 1, &m_vertices, &stride, &offset);
context->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
//D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST
context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_LINELIST);
context->DrawIndexed(2, 0, 0);
return hr;
}
//--------------------------------------------------------------------------------------
// File: Tutorial03.cpp
//
// This application displays a triangle using Direct3D 11
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//--------------------------------------------------------------------------------------
#include <windows.h>
#include <d3d11.h>
#include <d3dx11.h>
#include <d3dcompiler.h>
#include <xnamath.h>
#include "resource.h"
#include "RayRenderClass.h"
//--------------------------------------------------------------------------------------
// Structures
//--------------------------------------------------------------------------------------
struct SimpleVertex
{
XMFLOAT3 Pos;
};
//--------------------------------------------------------------------------------------
// Global Variables
//--------------------------------------------------------------------------------------
HINSTANCE g_hInst = NULL;
HWND g_hWnd = NULL;
D3D_DRIVER_TYPE g_driverType = D3D_DRIVER_TYPE_NULL;
D3D_FEATURE_LEVEL g_featureLevel = D3D_FEATURE_LEVEL_11_0;
ID3D11Device* g_pd3dDevice = NULL;
ID3D11DeviceContext* g_pImmediateContext = NULL;
IDXGISwapChain* g_pSwapChain = NULL;
ID3D11RenderTargetView* g_pRenderTargetView = NULL;
ID3D11VertexShader* g_pVertexShader = NULL;
ID3D11PixelShader* g_pPixelShader = NULL;
ID3D11InputLayout* g_pVertexLayout = NULL;
ID3D11Buffer* g_pVertexBuffer = NULL;
ID3D11Buffer* g_index = NULL;
RayRenderClass m_ray;
//--------------------------------------------------------------------------------------
// Forward declarations
//--------------------------------------------------------------------------------------
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow );
HRESULT InitDevice();
void CleanupDevice();
LRESULT CALLBACK WndProc( HWND, UINT, WPARAM, LPARAM );
void Render();
//--------------------------------------------------------------------------------------
// Entry point to the program. Initializes everything and goes into a message processing
// loop. Idle time is used to render the scene.
//--------------------------------------------------------------------------------------
int WINAPI wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPWSTR lpCmdLine, int nCmdShow )
{
UNREFERENCED_PARAMETER( hPrevInstance );
UNREFERENCED_PARAMETER( lpCmdLine );
if( FAILED( InitWindow( hInstance, nCmdShow ) ) )
return 0;
if( FAILED( InitDevice() ) )
{
CleanupDevice();
return 0;
}
// Main message loop
MSG msg = {0};
while( WM_QUIT != msg.message )
{
if( PeekMessage( &msg, NULL, 0, 0, PM_REMOVE ) )
{
TranslateMessage( &msg );
DispatchMessage( &msg );
}
else
{
Render();
}
}
CleanupDevice();
return ( int )msg.wParam;
}
//--------------------------------------------------------------------------------------
// Register class and create window
//--------------------------------------------------------------------------------------
HRESULT InitWindow( HINSTANCE hInstance, int nCmdShow )
{
// Register class
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( hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
wcex.hCursor = LoadCursor( NULL, IDC_ARROW );
wcex.hbrBackground = ( HBRUSH )( COLOR_WINDOW + 1 );
wcex.lpszMenuName = NULL;
wcex.lpszClassName = L"TutorialWindowClass";
wcex.hIconSm = LoadIcon( wcex.hInstance, ( LPCTSTR )IDI_TUTORIAL1 );
if( !RegisterClassEx( &wcex ) )
return E_FAIL;
// Create window
g_hInst = hInstance;
RECT rc = { 0, 0, 640, 480 };
AdjustWindowRect( &rc, WS_OVERLAPPEDWINDOW, FALSE );
g_hWnd = CreateWindow( L"TutorialWindowClass", L"Direct3D 11 Tutorial 3: Shaders",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, rc.right - rc.left, rc.bottom - rc.top, NULL, NULL, hInstance,
NULL );
if( !g_hWnd )
return E_FAIL;
ShowWindow( g_hWnd, nCmdShow );
return S_OK;
}
//--------------------------------------------------------------------------------------
// Helper for compiling shaders with D3DX11
//--------------------------------------------------------------------------------------
HRESULT CompileShaderFromFile( WCHAR* szFileName, LPCSTR szEntryPoint, LPCSTR szShaderModel, ID3DBlob** ppBlobOut )
{
HRESULT hr = S_OK;
DWORD dwShaderFlags = D3DCOMPILE_ENABLE_STRICTNESS;
#if defined( DEBUG ) || defined( _DEBUG )
// Set the D3DCOMPILE_DEBUG flag to embed debug information in the shaders.
// Setting this flag improves the shader debugging experience, but still allows
// the shaders to be optimized and to run exactly the way they will run in
// the release configuration of this program.
dwShaderFlags |= D3DCOMPILE_DEBUG;
#endif
ID3DBlob* pErrorBlob;
hr = D3DX11CompileFromFile( szFileName, NULL, NULL, szEntryPoint, szShaderModel,
dwShaderFlags, 0, NULL, ppBlobOut, &pErrorBlob, NULL );
if( FAILED(hr) )
{
if( pErrorBlob != NULL )
OutputDebugStringA( (char*)pErrorBlob->GetBufferPointer() );
if( pErrorBlob ) pErrorBlob->Release();
return hr;
}
if( pErrorBlob ) pErrorBlob->Release();
return S_OK;
}
//--------------------------------------------------------------------------------------
// Create Direct3D device and swap chain
//--------------------------------------------------------------------------------------
HRESULT InitDevice()
{
HRESULT hr = S_OK;
RECT rc;
GetClientRect( g_hWnd, &rc );
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
UINT createDeviceFlags = 0;
#ifdef _DEBUG
createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_DRIVER_TYPE driverTypes[] =
{
D3D_DRIVER_TYPE_HARDWARE,
D3D_DRIVER_TYPE_WARP,
D3D_DRIVER_TYPE_REFERENCE,
};
UINT numDriverTypes = ARRAYSIZE( driverTypes );
D3D_FEATURE_LEVEL featureLevels[] =
{
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
};
UINT numFeatureLevels = ARRAYSIZE( featureLevels );
DXGI_SWAP_CHAIN_DESC sd;
ZeroMemory( &sd, sizeof( sd ) );
sd.BufferCount = 1;
sd.BufferDesc.Width = width;
sd.BufferDesc.Height = height;
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
sd.BufferDesc.RefreshRate.Numerator = 60;
sd.BufferDesc.RefreshRate.Denominator = 1;
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
sd.OutputWindow = g_hWnd;
sd.SampleDesc.Count = 1;
sd.SampleDesc.Quality = 0;
sd.Windowed = TRUE;
for( UINT driverTypeIndex = 0; driverTypeIndex < numDriverTypes; driverTypeIndex++ )
{
g_driverType = driverTypes[driverTypeIndex];
hr = D3D11CreateDeviceAndSwapChain( NULL, g_driverType, NULL, createDeviceFlags, featureLevels, numFeatureLevels,
D3D11_SDK_VERSION, &sd, &g_pSwapChain, &g_pd3dDevice, &g_featureLevel, &g_pImmediateContext );
if( SUCCEEDED( hr ) )
break;
}
if( FAILED( hr ) )
return hr;
// Create a render target view
ID3D11Texture2D* pBackBuffer = NULL;
hr = g_pSwapChain->GetBuffer( 0, __uuidof( ID3D11Texture2D ), ( LPVOID* )&pBackBuffer );
if( FAILED( hr ) )
return hr;
hr = g_pd3dDevice->CreateRenderTargetView( pBackBuffer, NULL, &g_pRenderTargetView );
pBackBuffer->Release();
if( FAILED( hr ) )
return hr;
g_pImmediateContext->OMSetRenderTargets( 1, &g_pRenderTargetView, NULL );
// Setup the viewport
D3D11_VIEWPORT vp;
vp.Width = (FLOAT)width;
vp.Height = (FLOAT)height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
g_pImmediateContext->RSSetViewports( 1, &vp );
// Compile the vertex shader
ID3DBlob* pVSBlob = NULL;
hr = CompileShaderFromFile( L"Tutorial03.fx", "VS", "vs_4_0", &pVSBlob );
if( FAILED( hr ) )
{
MessageBox( NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hr;
}
// Create the vertex shader
hr = g_pd3dDevice->CreateVertexShader( pVSBlob->GetBufferPointer(), pVSBlob->GetBufferSize(), NULL, &g_pVertexShader );
if( FAILED( hr ) )
{
pVSBlob->Release();
return hr;
}
// Define the input layout
D3D11_INPUT_ELEMENT_DESC layout[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 },
};
UINT numElements = ARRAYSIZE( layout );
// Create the input layout
hr = g_pd3dDevice->CreateInputLayout( layout, numElements, pVSBlob->GetBufferPointer(),
pVSBlob->GetBufferSize(), &g_pVertexLayout );
pVSBlob->Release();
if( FAILED( hr ) )
return hr;
// Set the input layout
g_pImmediateContext->IASetInputLayout( g_pVertexLayout );
// Compile the pixel shader
ID3DBlob* pPSBlob = NULL;
hr = CompileShaderFromFile( L"Tutorial03.fx", "PS", "ps_4_0", &pPSBlob );
if( FAILED( hr ) )
{
MessageBox( NULL,
L"The FX file cannot be compiled. Please run this executable from the directory that contains the FX file.", L"Error", MB_OK );
return hr;
}
// Create the pixel shader
hr = g_pd3dDevice->CreatePixelShader( pPSBlob->GetBufferPointer(), pPSBlob->GetBufferSize(), NULL, &g_pPixelShader );
pPSBlob->Release();
if( FAILED( hr ) )
return hr;
// Create vertex buffer
SimpleVertex vertices[] =
{
XMFLOAT3( 0.0f, 0.5f, 0.5f ),
XMFLOAT3( 0.5f, -0.5f, 0.5f ),
XMFLOAT3( -0.5f, -0.5f, 0.5f ),
};
D3D11_BUFFER_DESC bd;
ZeroMemory( &bd, sizeof(bd) );
bd.Usage = D3D11_USAGE_DEFAULT;
bd.ByteWidth = sizeof( SimpleVertex ) * 3;
bd.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bd.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA InitData;
ZeroMemory( &InitData, sizeof(InitData) );
InitData.pSysMem = vertices;
hr = g_pd3dDevice->CreateBuffer( &bd, &InitData, &g_pVertexBuffer );
if( FAILED( hr ) )
return hr;
// Set vertex buffer
UINT stride = sizeof( SimpleVertex );
UINT offset = 0;
D3D11_BUFFER_DESC indexDesc;
D3D11_SUBRESOURCE_DATA indexData;
g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );
// Set primitive topology
g_pImmediateContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST );
UINT indices[] = {0,1,2};
ZeroMemory(&indexDesc, sizeof(indexDesc));
indexDesc.Usage = D3D11_USAGE_DEFAULT;
indexDesc.ByteWidth = sizeof(ULONG)* 3;
indexDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
ZeroMemory(&indexData, sizeof(indexData));
indexData.pSysMem = indices;
indexData.SysMemPitch = 0;
indexData.SysMemSlicePitch = 0;
hr = g_pd3dDevice->CreateBuffer(&indexDesc, &indexData, &g_index);
if (FAILED(hr))
{
return hr;
}
m_ray.Initialize(g_pd3dDevice, g_pImmediateContext);
return S_OK;
}
//--------------------------------------------------------------------------------------
// Clean up the objects we've created
//--------------------------------------------------------------------------------------
void CleanupDevice()
{
if( g_pImmediateContext ) g_pImmediateContext->ClearState();
if( g_pVertexBuffer ) g_pVertexBuffer->Release();
if( g_pVertexLayout ) g_pVertexLayout->Release();
if( g_pVertexShader ) g_pVertexShader->Release();
if( g_pPixelShader ) g_pPixelShader->Release();
if( g_pRenderTargetView ) g_pRenderTargetView->Release();
if( g_pSwapChain ) g_pSwapChain->Release();
if( g_pImmediateContext ) g_pImmediateContext->Release();
if( g_pd3dDevice ) g_pd3dDevice->Release();
}
//--------------------------------------------------------------------------------------
// Called every time the application receives a message
//--------------------------------------------------------------------------------------
LRESULT CALLBACK WndProc( HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam )
{
PAINTSTRUCT ps;
HDC hdc;
switch( message )
{
case WM_PAINT:
hdc = BeginPaint( hWnd, &ps );
EndPaint( hWnd, &ps );
break;
case WM_DESTROY:
PostQuitMessage( 0 );
break;
default:
return DefWindowProc( hWnd, message, wParam, lParam );
}
return 0;
}
//--------------------------------------------------------------------------------------
// Render a frame
//--------------------------------------------------------------------------------------
void Render()
{
// Clear the back buffer
float ClearColor[4] = { 0.0f, 0.125f, 0.3f, 1.0f }; // red,green,blue,alpha
g_pImmediateContext->ClearRenderTargetView( g_pRenderTargetView, ClearColor );
g_pImmediateContext->IASetIndexBuffer(g_index, DXGI_FORMAT_R32_UINT, 0);
g_pImmediateContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Render a triangle
g_pImmediateContext->VSSetShader( g_pVertexShader, NULL, 0 );
g_pImmediateContext->PSSetShader( g_pPixelShader, NULL, 0 );
g_pImmediateContext->DrawIndexed( 3, 0 ,0);
// Present the information rendered to the back buffer to the front buffer (the screen)
m_ray.Render(g_pd3dDevice, g_pImmediateContext);
g_pSwapChain->Present(0, 0);
}
In your render method, you don't set the vertex buffer for your triangle (only on initialization), so by calling
m_ray.Render(g_pd3dDevice, g_pImmediateContext);
You permanently set the pipeline to use your line buffer instead.
Make sure that the following line is called within your render function, to properly assign your triangle before the draw:
g_pImmediateContext->IASetVertexBuffers( 0, 1, &g_pVertexBuffer, &stride, &offset );
For you ray, you should not even need an index buffer, you can get rid of it and use:
g_pImmediateContext->Draw(2,0);
For the same effect

DirectX10 don't writes text

Tried to write text, but program does not work.
P.S. program uses multibyte encoding.
Code:
#include <Windows.h>
#include <d3d10.h>
#include <d3dx10.h>
LPCSTR ClassName = "MyClass";
LPCSTR ProgName = "MyProg";
const int WINDOW_WIDTH = 640;
const int WINDOW_HEIGHT= 480;
HWND g_hWnd;
D3D10_DRIVER_TYPE g_driverType = D3D10_DRIVER_TYPE_NULL;
ID3D10Device* g_pd3dDevice = NULL;
IDXGISwapChain* g_pSwapChain = NULL;
ID3D10RenderTargetView* g_pRenderTargetView=NULL;
ID3DX10Font* g_pFont=NULL;
HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow);
void ResizeBuffers();
HRESULT InitDirect3D10();
HRESULT Cleanup();
void RenderScene();
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
// Регистрируем класс окна и создаем окно
if (FAILED( InitWindow(hInstance, nCmdShow)))
return E_FAIL;
// Инициализируем Direct3D 10
if(FAILED( InitDirect3D10()))
{
Cleanup();
return E_FAIL;
}
// Цикл обработки сообщений
MSG msg={0};
while(WM_QUIT != msg.message)
{
if(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else RenderScene();
}
Cleanup();
return (int) msg.wParam;
}
HRESULT InitWindow(HINSTANCE hInstance, int nCmdShow)
{
// Заполняем структуру класса окна
WNDCLASSEX wc;
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground= (HBRUSH)COLOR_WINDOW;
wc.lpszMenuName = NULL;
wc.lpszClassName= ClassName;
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
if (!RegisterClassEx(&wc))
return E_FAIL;
// Создание окна
g_hWnd = CreateWindow(
ClassName,
ProgName,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
WINDOW_WIDTH,
WINDOW_HEIGHT,
NULL,
NULL,
hInstance,
NULL);
// Если не удалось создать окно - выходим из функции
if (!g_hWnd)
return E_FAIL;
// Отображаем окно на экране
ShowWindow(g_hWnd, nCmdShow);
return S_OK;
}
void ResizeBuffers()
{
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
case WM_KEYDOWN:
if (VK_F1==wParam)
{
BOOL InFullScreen;
g_pSwapChain->GetFullscreenState(&InFullScreen, NULL);
g_pSwapChain->SetFullscreenState(!InFullScreen, NULL);
}
break;
case WM_SIZE:
ResizeBuffers();
break;
default: return DefWindowProc(hWnd, msg, wParam, lParam);
}
return 0;
}
HRESULT InitDirect3D10()
{
D3D10_DRIVER_TYPE driverTypes[] =
{
D3D10_DRIVER_TYPE_HARDWARE,
D3D10_DRIVER_TYPE_REFERENCE
};
UINT numDriverTypes = sizeof(driverTypes) / sizeof(driverTypes[0]);
DXGI_SWAP_CHAIN_DESC sd;
HRESULT hr = S_OK;
//Вычисляем размеры клиентской области окна
RECT rc;
GetClientRect( g_hWnd, &rc);
UINT width = rc.right - rc.left;
UINT height = rc.bottom - rc.top;
//Заполняем структуру цепочки переключений
ZeroMemory(&sd, sizeof(sd)); // Заполняем структуру нулевыми значениями
sd.BufferCount = 1; //Количество вторичных буферов
sd.BufferDesc.Width = width; //Ширина вторичного буфера в пикселах
sd.BufferDesc.Height = height; //Высота вторичного буфера в пикселах
sd.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;//Формат вторичного буфера
sd.BufferDesc.RefreshRate.Numerator = 60;//Частота смены кадров. Игнорируется оконном режиме
sd.BufferDesc.RefreshRate.Denominator = 1;//Минимальное значение количества кадров
sd.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;//Определяет, как испльзовать вторичный буфер
sd.OutputWindow = g_hWnd; //Окно, в которое будет производиться вывод графики
sd.SampleDesc.Count = 1; // параметры сглаживания изображения с использованием
sd.SampleDesc.Quality = 0; // мультисэмплинга. В данном случае не используется
sd.Windowed = TRUE;//Полноэкранный, или экранный режим
sd.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;//Вариант переключения буферов (в данном случае полное
//стирание предыдущего кадра)
// Пытаемся создать устройство и цепочку переключений
for (UINT driverTypeIndex =0; driverTypeIndex<numDriverTypes;driverTypeIndex++)
{
g_driverType = driverTypes[driverTypeIndex];
hr = D3D10CreateDeviceAndSwapChain(NULL,
g_driverType,
NULL,
0,
D3D10_SDK_VERSION,
&sd,
&g_pSwapChain,
&g_pd3dDevice);
if(SUCCEEDED(hr))break;
}
if( FAILED(hr)) // Проверка правильности выполнения предыдущей фунции
return hr;
// Представление данных как буфера визуализации
ID3D10Texture2D *pBackBuffer;
// Получим доступ к вторичному буферу через переменную для текстуры
hr = g_pSwapChain->GetBuffer(0, // Индекс вторичного буфера
__uuidof(ID3D10Texture2D),
(LPVOID*)&pBackBuffer);
if ( FAILED(hr))
return hr;
// Данные о вторичном буфере из текстуры в подходящую переменную
hr = g_pd3dDevice->CreateRenderTargetView(pBackBuffer, NULL,&g_pRenderTargetView);
// освобождаем "текстурную" переменную в памяти
pBackBuffer->Release();
// Свяжем буфер визуализации с графическим конвейером
D3D10_VIEWPORT vp;
vp.Width = width;
vp.Height = height;
vp.MinDepth = 0.0f;
vp.MaxDepth = 1.0f;
vp.TopLeftX = 0;
vp.TopLeftY = 0;
g_pd3dDevice->RSSetViewports(1,&vp);
return S_OK;
}
HRESULT Cleanup()
{
if(g_pd3dDevice) g_pd3dDevice->ClearState();
if(g_pFont) g_pFont->Release();
if(g_pRenderTargetView) g_pRenderTargetView->Release();
if(g_pSwapChain) g_pSwapChain->Release();
if(g_pd3dDevice) g_pd3dDevice->Release();
D3DX10CreateFont(g_pd3dDevice, //Указатель на интерфейс устройства, с которым будет связан шрифтовый объект
14, //Высота букв ( в пикселах)
8, //Ширина букв ( в пикселах)
1, //Толщина линий символа шрифта
1, //Количество уровней миммаппинга(при отдалении, приближении камеры)
false, //Наклонное начертание
0, //Код символьного набора шрифта
0, //Настройки согласования размеров шрифтов с оригинальными размерами шрифтов
0, //указывает каким образом система Windows должна согласовывать желаемый и реально используемый шрифт. Приминяется только к растровым шрифтам
DEFAULT_PITCH|FF_MODERN, //Информация о шаги символов в строке и принадлежности к тому или иному семейству
"Verdana", // имя желаемого шрифта
&g_pFont); // Куда записывать результат работы функции
return S_OK;
}
void RenderScene()
{
// Очищаем вторичный буфер
// (компоненты красного, зеленого, синего, прозрачность)
float ClearColor[4] = {1.0f, 1.0f, 1.0f, 1.0f};
// Очищаем буфер
g_pd3dDevice->ClearRenderTargetView(g_pRenderTargetView,ClearColor);
// Размеры прямоугольниа для форматирования текста
RECT Rect;
Rect.left=10;
Rect.top=10;
Rect.right=600;
Rect.bottom=380;
g_pFont->DrawText(NULL, // Указатель на спрайтовый объект. Выбран по умолчанию
"ClearCode",
-1, // Количество символов. В данном случае подсчитано автоматически
&Rect, // Область в которую будет выводиться надпись
DT_CENTER|DT_VCENTER,//Способ форматирования текста
D3DXCOLOR(1.0,1.0,1.0,1.0));//Цвет выводимого текста
g_pSwapChain->Present(0,0);
}
Why did you create font in Cleanup function? it won't be called unit
you quit, and when you quit, you will see nothing.
Don't use D3DXCOLOR(1.0,1.0,1.0,1.0), that's white color which was same as
your window's background, you will see nothing.
Don't forgot to call OMSetRenderTargets after you create the rendertargetview, or you
will see nothing.
By the way, Do not use non-English comments, StackOverFlow is a world wide web site, English is the first choice since most people here know English

LNK2019 unresolved external symbol user32.lib

I am at a loss as to why I am getting this error:
test_project.obj : error LNK2019: unresolved external symbol "int __cdecl run(void)" (?run##YAHXZ) referenced in function _WinMain#16
code is as follows:
#include "stdafx.h"
#include "test_project.h"
#include <Windows.h>
HWND ghMainWnd = 0;
bool InitWindowsApp (HINSTANCE instanceHandle, int show);
int run();
LRESULT CALLBACK
WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nShowCmd) {
if (!InitWindowsApp (hInstance, nShowCmd) )
return 0;
return run();
}
bool InitWindowsApp (HINSTANCE instanceHandle, int show) {
WNDCLASS wc;
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = instanceHandle;
wc.hIcon = LoadIcon( 0, IDI_APPLICATION );
wc.hCursor = LoadCursor( 0 , IDC_ARROW );
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = 0;
wc.lpszClassName = L"BasicWndClass";
if (!RegisterClass(&wc) ) {
MessageBox(0, L"RegisterClass FAILED", 0, 0);
return false;
}
ghMainWnd = CreateWindow (
L"BasicWndClass",
L"Win32Basic",
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
0,
0,
instanceHandle,
0);
if (ghMainWnd == 0) {
MessageBox ( 0, L"CreateWindow FAILED", 0, 0);
return false;
}
ShowWindow (ghMainWnd, show);
UpdateWindow (ghMainWnd);
return true;
}
int Run() {
MSG msg = {0};
BOOL bRet = 1;
while ((bRet = GetMessage(&msg, 0, 0, 0)) != 0) {
if (bRet == -1)
{
MessageBox(0, L"GetMessage FAILED", L"Error", MB_OK);
break;
}
else {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int)msg.wParam;
}
LRESULT CALLBACK
WndProc ( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
switch(msg) {
case WM_LBUTTONDOWN:
MessageBox(0, L"Hello, World", L"Hello", MB_OK);
return 0;
case WM_KEYDOWN:
if (wParam == VK_ESCAPE)
DestroyWindow(ghMainWnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc (hWnd, msg, wParam, lParam);
}
In the property pages->c/c++->general->additional include directories I have put the directory containing the lib: C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib
In property pages->linker->input->additional dependencies I have put the full path to the lib C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\user32.lib
In property pages->linker->system->subsystem I have put Windows (/SUBSYSTEM:WINDOWS)
I am at a loss as to what to try next.
C++ is case-sensitive. You have to decide whether to name your function run() or Run().
int run();
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR pCmdLine, int nShowCmd) {
if (!InitWindowsApp (hInstance, nShowCmd) )
return 0;
return run(); // <-- There.
}
Versus:
int Run() {
// ...
}

Resources