How to avoid an Invalid Argument exception when calling SetControlText in a CFileDialog - mfc

I inherited some code that is clearly based on this discussion:
cfiledialog and file extension
The code reads:
#define FILE_DIALOG_NAME cmb13
// CStarMaskDlg dialog
/* ------------------------------------------------------------------- */
class CSaveMaskDlg : public CFileDialog
{
DECLARE_DYNAMIC(CSaveMaskDlg)
//
// 9 December 2022 David C. Partridge
//
// I added OFN_EXPLORER to the open flags as per the note in the docs for CFileDialog::SetControlText
// that say:
// To use this method, you must create the dialog box with the OFN_EXPLORER style.
// Otherwise, the function will fail with an assertion.
//
public :
CSaveMaskDlg(bool bOpenFileDialog, // true for FileOpen, false for FileSaveAs
LPCTSTR lpszDefExt = nullptr,
LPCTSTR lpszFileName = nullptr,
DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_EXPLORER, // Add OFN_EXPLORER - see CFileDialog
LPCTSTR lpszFilter = nullptr,
CWnd* pParentWnd = nullptr):CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd)
{
};
virtual ~CSaveMaskDlg()
{
};
protected:
virtual void OnTypeChange()
{
CFileDialog::OnTypeChange();
CString strFileName = GetFileTitle();
if (strFileName.GetLength())
{
if (m_ofn.nFilterIndex == 1)
strFileName += ".tif";
else
strFileName += ".fits";
SetControlText(FILE_DIALOG_NAME, strFileName);
};
};
};
IMPLEMENT_DYNAMIC(CSaveMaskDlg, CFileDialog)
/* ------------------------------------------------------------------- */
IMPLEMENT_DYNAMIC(CStarMaskDlg, CDialog)
The problem is that whenever SetControlText is invoked (at least on W10 and W11), an InvalidArgument exception is thrown.
As you can see I tried to fix the problem but so far it is beating me.
If this code is wrong, then please put me out of my misery and show me how it should go.
Thanks a lot
David

Related

Disabling "Script Error" popup IWebBrowser2 c++ WinApi

Having a HWND with IWebBrowser2 on it. IWebBrowser2 is new CLSID_WEBBROWSER.
When I navigating to youtube,google and etc, sometimes it shows me Script Error. And I want to disable it. How can I do it?
if (MoneyHWND == NULL) {
if (SUCCEEDED(OleInitialize(NULL)))
{
vector<wchar_t> fn(1000);
GetModuleFileName(0, fn.data(), 1000);
PathStripPath(fn.data());
RKEY k(HKEY_CURRENT_USER, L"SOFTWARE\\Microsoft\\Internet Explorer\\Main\\FeatureControl\\FEATURE_BROWSER_EMULATION");
k[fn.data()] = 11001UL; // Use IE 11
MoneyHWND = CreateDialog(GetModuleHandle(0), MAKEINTRESOURCE(IDD_FORMVIEW1), hWnd, MoneyProc);
pBrowser2 = new WebBrowser(MoneyHWND);
RECT rc;
GetClientRect(MoneyHWND, &rc);
pBrowser2->SetRect(rc);
pBrowser2->Navigate(site);
OleUninitialize();
}
}
IWebBrowser2::Silent:
Sets or gets a value that indicates whether the object can display dialog boxes.
Note, that the property is exposed to C and C++ programs using the following signatures:
HRESULT IWebBrowser2::get_Silent(VARIANT_BOOL *pbSilent);
HRESULT IWebBrowser2::put_Silent(VARIANT_BOOL bSilent);
In other words:
// ...
auto hr{ pBrowser2->put_Silent(VARIANT_TRUE) };
if FAILED(hr)
{
// Handle error
// ...
}

C++ Windows Credential Provider Progress Screen

I am developing a custom credential provider and I have to show a progress screen with a cancel button. I have seen in some credentials providers and pgina plugins that a screen is displayed with a Cancel button when credential provider is working. I have attached a screenshot of it. I have managed to show the error screen with an Ok button using the following code:
*pcpgsr = CPGSR_NO_CREDENTIAL_NOT_FINISHED;
SHStrDupW(L"Authentication Failed", ppwszOptionalStatusText);
*pcpsiOptionalStatusIcon = CPSI_ERROR;
Now I need to show this progress screen with a cancel button. Any advice how can it be achieved? Also, how to handle the event that fires when this button is pressed?
As I understand your scenario you want to do something in background presenting to the user "wait screen".
You must run a separate thread for background work and change the layout of your credential tile to leave visible only one text element with "Wait..." content and no submit button.
Once your background thread complete its work you may reveal submit button and let user to continue to logon.
For example, have a look at embedded Smartcard Credential Porvider and its behaviour on insertion and removal of the card.
#js.hrt You can run your main thread as dialog, while your background thread does the job. The cancel button would be the control in the dialog, allowing to cancel it. If you need more info, let me know, I can provide some details, as this is the way we do it.
#js.hrt Briefly, you need two classes: dialog and thread.
When you create a dialog, it will create a thread, which will run what you need, and show cancel button. Clicking on it will terminate your thread. Some code below. Hope it helps.
class Thread {
public:
Thread(GUI* object);
virtual ~Thread();
bool start( bool ) {
::CreateThread( NULL, 0, threadRun, lpParameter, dwCreationFlags,
&m_dwThreadId );
}
static DWORD WINAPI threadRun( void* lpVoid ) {
DWORD dwReturn( 0 );
dwReturn = m_object->yourProcessToRun();
return dwReturn;
}
protected:
GUI* m_object;
Runnable* m_lpRunnable;
};
Then, class for your UI, similar to this
#include "atlwin.h"
class GUI: public CDialogImpl<GUI> {
public:
enum { IDD = IDD_FOR_YOUR_DIALOG };
GUI();
~GUI();
BEGIN_MSG_MAP(GUI)
MESSAGE_HANDLER(WM_INITDIALOG,OnInitDialog)
COMMAND_ID_HANDLER(ID_CANCEL,OnCancel)
MESSAGE_HANDLER(WM_TIMER,OnTimer)
MESSAGE_HANDLER(WM_DESTROY,OnDestroy)
END_MSG_MAP()
LRESULT OnInitDialog(UINT,WPARAM,LPARAM, BOOL&) {
myThread = new Thread(this);
m_nTimerID = SetTimer(1,3000,NULL);
myThread->start();
}
LRESULT OnCancel(WORD,WORD,HWND,BOOL& ) {
if(NULL != myThread) {
DWORD exitCode = 0;
myThread->getExitCode(exitCode);
if(exitCode == STILL_ACTIVE)
myThread->terminate();
delete myThread;
myThread = NULL;
}
EndDialog(IDCANCEL);
return true;
}
LRESULT OnTimer(UINT,WPARAM wParam,LPARAM,BOOL&) {
if(wParam != m_nTimerID)
return FALSE;
m_timerticks++;
return FALSE;
}
LRESULT OnDestroy(UINT,WPARAM,LPARAM,BOOL&) {
KillTimer(m_nTimerID);
return FALSE;
}
virtual int yourProcessToRun() {};
void onFinishProgress(int retCode = IDOK) {
if (retCode != IDCANCEL) {
delete myThread;
myThread = NULL;
KillTimer(m_nTimerID);
EndDialog(retCode);
}
}
private:
Thread* myThread;
UINT m_nTimerID;
UINT m_timerticks;
};
The resource for dialog could be like this:
IDD_FOR_YOUR_DIALOG DIALOGEX 0, 0, 309, 80
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP
| WS_CAPTION
CAPTION "Whatever"
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
PUSHBUTTON "Cancel",ID_CANCEL,113,50,84,14
CTEXT "Static",IDC_FOR_SOMETHING,7,7,295,20
END
#js.hrt If you don't mind to post your code, I'll make it run.
Can't comment to your's message directly, as I limit by site
requirements
#js.hrt Per your request.
class Thread {
public:
Thread(GUI* object);
virtual ~Thread();
bool start( bool ) {
::CreateThread( NULL, 0, threadRun, lpParameter, dwCreationFlags,
&m_dwThreadId );
}
static DWORD WINAPI threadRun( void* lpVoid ) {
DWORD dwReturn( 0 );
dwReturn = m_object->yourProcessToRun();
return dwReturn;
}
protected:
GUI* m_object;
Runnable* m_lpRunnable;
};
Then, class for your UI, similar to this
#include "atlwin.h"
class GUI: public CDialogImpl<GUI> {
public:
enum { IDD = IDD_FOR_YOUR_DIALOG };
GUI();
~GUI();
BEGIN_MSG_MAP(GUI)
MESSAGE_HANDLER(WM_INITDIALOG,OnInitDialog)
COMMAND_ID_HANDLER(ID_CANCEL,OnCancel)
MESSAGE_HANDLER(WM_TIMER,OnTimer)
MESSAGE_HANDLER(WM_DESTROY,OnDestroy)
END_MSG_MAP()
LRESULT OnInitDialog(UINT,WPARAM,LPARAM, BOOL&) {
myThread = new Thread(this);
m_nTimerID = SetTimer(1,3000,NULL);
myThread->start();
}
LRESULT OnCancel(WORD,WORD,HWND,BOOL& ) {
if(NULL != myThread) {
DWORD exitCode = 0;
myThread->getExitCode(exitCode);
if(exitCode == STILL_ACTIVE)
myThread->terminate();
delete myThread;
myThread = NULL;
}
EndDialog(IDCANCEL);
return true;
}
LRESULT OnTimer(UINT,WPARAM wParam,LPARAM,BOOL&) {
if(wParam != m_nTimerID)
return FALSE;
m_timerticks++;
return FALSE;
}
LRESULT OnDestroy(UINT,WPARAM,LPARAM,BOOL&) {
KillTimer(m_nTimerID);
return FALSE;
}
virtual int yourProcessToRun() {};
void onFinishProgress(int retCode = IDOK) {
if (retCode != IDCANCEL) {
delete myThread;
myThread = NULL;
KillTimer(m_nTimerID);
EndDialog(retCode);
}
}
private:
Thread* myThread;
UINT m_nTimerID;
UINT m_timerticks;
};
The resource for dialog could be like this:
IDD_FOR_YOUR_DIALOG DIALOGEX 0, 0, 309, 80
STYLE DS_SETFONT | DS_MODALFRAME | DS_FIXEDSYS | DS_CENTER | WS_POPUP
| WS_CAPTION
CAPTION "Whatever"
FONT 8, "MS Shell Dlg", 400, 0, 0x0
BEGIN
PUSHBUTTON "Cancel",ID_CANCEL,113,50,84,14
CTEXT "Static",IDC_FOR_SOMETHING,7,7,295,20
END
I assume you are looking for IConnectableCredentialProviderCredential::Connect().
You need to implement the IConnectableCredentialProviderCredentialinterface and put your logic to the Connect() function. It is called right after Submit button pressed.
The Connect() function will give you the IQueryContinueWithStatus interface. In this interface you need to call the QueryContinue() function periodically, to handle Cancel button or some system events.
For more information look at this article: https://learn.microsoft.com/en-us/windows/win32/api/credentialprovider/nf-credentialprovider-iconnectablecredentialprovidercredential-connect

Local html (RoboHelp) index online help file under MFC is not opened

I followed all the instructions that is referred here :
http://help.adobe.com/en_US/robohelp/robohtml/WS5b3ccc516d4fbf351e63e3d11aff59c571-7f43.html
My CMainFrame::HtmlHelp overiden handler looks like this :
void CMainFrame::HtmlHelp(DWORD_PTR dwData, UINT nCmd)
{
// TODO: Add your specialized code here and/or call the base class
CWaitCursor wait;
// Get the path to the Help system
CWinApp* pApp = AfxGetApp();
ASSERT_VALID(pApp);
// Set the path to server-based help
CString csOnlineHelpPath = _T("C:\\Help\\Final\\index.htm");
PrepareForHelp();
// must use top level parent (for the case where m_hWnd is in DLL)
CWnd* pWnd = GetTopLevelParent();
// finally, run the RoboHelp Help engine
if (!RH_ShowHelp(pWnd->m_hWnd, csOnlineHelpPath, nCmd, dwData))
AfxMessageBox(AFX_IDP_FAILED_TO_LAUNCH_HELP);
}
The problem is that the help is never opened. I tried to debug the RoboHelp_CSH.cpp file and I found out that at the line #3267 with the code
MultiByteToWideChar(CP_ACP, MB_USEGLYPHCHARS, szTempFile, (int)uLen, bstr, uLen+1);
the bstr buffer have an extra char at the end that makes the following code
hr=s_pstBrowser->Navigate(bstr, &vFlags, &vTargetFrameName, &vPostData, &vHeaders);
HWND hWnd;
hr=s_pstBrowser->get_HWND((long*)&hWnd);
if (SUCCEEDED(hr))
{
::SetForegroundWindow(hWnd);
}
::SysFreeString(bstr);
}
to fail. The original szTempFile has the data below
C:\Users\sdancer\AppData\Local\Temp\robohelp_csh.htm
and the bstr the the following (the DC2 is the symbol I show inside notepad++, unside VS2008 I see an up and down arrow).
C:\Users\sdancer\AppData\Local\Temp\robohelp_csh.htmDC2
What am I doing wrong here ?

Linker issue with Visual Studio 2010 Pro

I'm having a very frustrating issue setting up a DirectX 9 (irrelevant to the issue.. I think) framework in VS 2010. Here is my DirectX framework:
#ifndef _DX9_H_
#define _DX9_H_
// window includes
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
// required for ush typedef and window properties to setup backbuffer
#include "sys_params.h"
// directx9 includes
#define DIRECTINPUT_VERSION 0x0800
#include <d3dx9.h>
#include <dinput.h>
#include <DxErr.h>
#include <vector>
#include <iterator>
// directx9 libraries
#pragma comment(lib, "d3d9.lib")
#pragma comment(lib, "d3dx9.lib")
#pragma comment(lib, "dinput8.lib")
#pragma comment(lib, "dxguid.lib")
#pragma comment(lib, "dxerr.lib")
namespace nsdx9
{
using nssysprms::ush;
#define CheckHR(hr) CheckForDXError(__FILE__, __LINE__, hr)
class DX9
{
public:
DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy);
~DX9();
// windows message processor
UINT ProcessMessages();
// --- DIRECTX GAME FUNCTIONS --- //
// input functions
void InputUpdate();
BYTE KeyHeld(ush key);
bool KeyPressed(ush key);
// sprite functions
const LPD3DXSPRITE& GetSpriteInterface();
void SpriteBeginDraw(DWORD flags = D3DXSPRITE_ALPHABLEND);
void SpriteEndDraw();
// font functions
void MakeFont(int height, int width, UINT weight = FW_DONTCARE, LPCSTR face = "Calibri", bool italic = false);
const LPD3DXFONT& GetFontAtIndex(ush index);
const std::vector<LPD3DXFONT>& GetFontVector();
// --- END DIRECTX GAME FUNCTIONS --- //
private:
// --- WINDOW FUNCTIONS/VARIABLES --- //
WNDCLASSEX _wc;
HWND _hwnd;
MSG _msg;
HINSTANCE _inst;
std::string _title;
static LRESULT CALLBACK WinProc(HWND hwnd, UINT msg, WPARAM wprm, LPARAM lprm);
// --- END WINDOW FUNCTIONS/VARIABLES --- //
// --- DIRECTX FUNCTIONS/VARIABLES --- //
// D3D interfaces
LPDIRECT3D9 _d3d;
LPDIRECT3DDEVICE9 _d3ddev;
D3DPRESENT_PARAMETERS _d3dpp;
// directinput interfaces
LPDIRECTINPUT8 _dInput;
LPDIRECTINPUTDEVICE8 _diMouse;
LPDIRECTINPUTDEVICE8 _diKeyboard;
DIMOUSESTATE _mouseState;
BYTE _keys[256];
bool _keyStates[256];
bool _keyboardStateChanged;
void AcquireInputDevice(const LPDIRECTINPUTDEVICE8& dev);
// sprite interfaces
LPD3DXSPRITE _spriteBatch;
// font vector
std::vector<LPD3DXFONT> _fonts;
// hresult checker, for debugging only
void CheckForDXError(const char *file, int line, HRESULT hr);
// --- END DIRECTX FUNCTIONS/VARIABLES --- //
};
/*=================================================*/
/*--------------DIRECTX CONSTRUCTOR----------------*/
/*=================================================*/
DX9::DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy)
{
/*=================================================*/
/*--------------WINDOW INITIALIZATION--------------*/
/*=================================================*/
_title = title;
_inst = inst;
// init window class struct
_wc.cbClsExtra = NULL;
_wc.cbSize = sizeof(WNDCLASSEX);
_wc.cbWndExtra = NULL;
_wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
_wc.hCursor = LoadCursor(NULL, IDC_ARROW);
_wc.hIcon = NULL;
_wc.hIconSm = NULL;
_wc.hInstance = inst;
_wc.lpfnWndProc = (WNDPROC)WinProc;
_wc.lpszClassName = title.c_str();
_wc.lpszMenuName = NULL;
_wc.style = CS_HREDRAW | CS_VREDRAW;
RegisterClassEx(&_wc);
// create handle to the window
_hwnd = CreateWindow(title.c_str(),
title.c_str(),
WS_OVERLAPPEDWINDOW,
wndx,
wndy,
wndwidth,
wndheight,
NULL,
NULL,
inst,
NULL);
// required to make the window show up
ShowWindow(_hwnd, cmdShow);
UpdateWindow(_hwnd);
/*=================================================*/
/*--------------END WINDOW INITIALIZATION----------*/
/*=================================================*/
/*=================================================*/
/*--------------DIRECTX INITIALIZATION-------------*/
/*=================================================*/
// --- INITIALIZE DIRECTX9 VARIABLES --- //
SecureZeroMemory(&_d3dpp, sizeof(_d3dpp));
SecureZeroMemory(&_mouseState, sizeof(_mouseState));
SecureZeroMemory(&_keys, sizeof(_keys));
for (int i = 0; i < 256; i++)
{
_keyStates[i] = true;
}
_d3d = NULL;
_d3ddev = NULL;
_dInput = NULL;
_diMouse = NULL;
_diKeyboard = NULL;
_keyboardStateChanged = false;
_spriteBatch = NULL;
// --- END INITIALIZE DIRECTX9 VARIABLES --- //
// --- DIRECTX9 INITIALIZATION --- //
_d3d = Direct3DCreate9(D3D_SDK_VERSION);
if (!_d3d)
{
OutputDebugString("Error: Failed to create Direct3D.\n");
}
// set d3d present parameters
_d3dpp.AutoDepthStencilFormat = D3DFMT_D24S8;
_d3dpp.BackBufferCount = 1;
_d3dpp.BackBufferFormat = D3DFMT_X8R8G8B8;
_d3dpp.BackBufferHeight = nssysprms::WND_HEIGHT;
_d3dpp.BackBufferWidth = nssysprms::WND_WIDTH;
_d3dpp.EnableAutoDepthStencil = 1;
_d3dpp.Flags = D3DPRESENTFLAG_DISCARD_DEPTHSTENCIL;
//_d3dpp.FullScreen_RefreshRateInHz
_d3dpp.hDeviceWindow = _hwnd;
//_d3dpp.MultiSampleQuality
//_d3dpp.MultiSampleType
_d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT;
_d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
_d3dpp.Windowed = nssysprms::isWindowed;
// create d3d device
CheckHR(_d3d->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, _hwnd, D3DCREATE_MIXED_VERTEXPROCESSING, &_d3dpp, &_d3ddev));
// --- END DIRECTX9 INITIALIZATION --- //
// --- INITIALIZE DIRECTINPUT --- //
CheckHR(DirectInput8Create(inst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&_dInput, NULL));
// create mouse and keyboard
CheckHR(_dInput->CreateDevice(GUID_SysKeyboard, &_diKeyboard, NULL));
CheckHR(_dInput->CreateDevice(GUID_SysMouse, &_diMouse, NULL));
// initialize keyboard
CheckHR(_diKeyboard->SetDataFormat(&c_dfDIKeyboard));
CheckHR(_diKeyboard->SetCooperativeLevel(_hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND));
AcquireInputDevice(_diKeyboard);
// initialize mouse
CheckHR(_diMouse->SetDataFormat(&c_dfDIMouse));
CheckHR(_diMouse->SetCooperativeLevel(_hwnd, DISCL_NONEXCLUSIVE | DISCL_FOREGROUND));
AcquireInputDevice(_diMouse);
// create sprite object
CheckHR(D3DXCreateSprite(_d3ddev, &_spriteBatch));
// --- END INITIALIZE DIRECTINPUT --- //
/*=================================================*/
/*--------------END DIRECTX INITIALIZATION---------*/
/*=================================================*/
}
/*=================================================*/
/*--------------END DIRECTX CONSTRUCTOR------------*/
/*=================================================*/
/*=================================================*/
/*--------------DIRECTX DESTRUCTOR-----------------*/
/*=================================================*/
DX9::~DX9()
{
// set all stack variables to NULL
SecureZeroMemory(&_d3dpp, sizeof(_d3dpp));
SecureZeroMemory(&_mouseState, sizeof(_mouseState));
SecureZeroMemory(&_keys, sizeof(_keys));
SecureZeroMemory(&_keyStates, sizeof(_keyStates));
// free all the D3D interfaces from memory
if (!_fonts.empty())
{
for (std::vector<LPD3DXFONT>::iterator it = _fonts.begin(); it != _fonts.end(); it++)
{
// SOLVEPROBLEM figure out why this doesn't work
//*it->OnLostDevice();
}
_fonts.erase(_fonts.begin(), _fonts.end() - 1);
}
if (_spriteBatch != NULL)
{
_spriteBatch->Release();
_spriteBatch = NULL;
}
if (_diKeyboard != NULL)
{
_diKeyboard->Release();
_diKeyboard = NULL;
}
if (_diMouse != NULL)
{
_diMouse->Release();
_diMouse = NULL;
}
if (_d3ddev != NULL)
{
_d3ddev->Release();
_d3ddev = NULL;
}
if (_d3d != NULL)
{
_d3d->Release();
_d3d = NULL;
}
// free the window class from memory
UnregisterClass(_title.c_str(), _inst);
}
/*=================================================*/
/*--------------END DIRECTX DESTRUCTOR-------------*/
/*=================================================*/
/*=================================================*/
/*--------------HRESULT ERROR CHECK----------------*/
/*=================================================*/
void DX9::CheckForDXError(const char *file, int line, HRESULT hr)
{
if (SUCCEEDED(hr))
{
return;
}
// Get the direct X error and description
char desc[1024];
sprintf_s(desc,"(DX) %s - %s", DXGetErrorString(hr), DXGetErrorDescription(hr));
// Output the file and line number in the correct format + the above DX error
char buf[2048];
sprintf_s(buf,"%s(%d) : Error: %s\n", file, line, desc);
OutputDebugString(buf);
}
/*=================================================*/
/*--------------END HRESULT ERROR CHECK------------*/
/*=================================================*/
/*=================================================*/
/*--------------MESSAGE PROCESSOR------------------*/
/*=================================================*/
UINT DX9::ProcessMessages()
{
if (PeekMessage(&_msg, NULL, NULL, NULL, PM_REMOVE))
{
TranslateMessage(&_msg);
DispatchMessage(&_msg);
}
return _msg.message;
}
/*=================================================*/
/*--------------END MESSAGE PROCESSOR--------------*/
/*=================================================*/
/*=================================================*/
/*--------------MESSAGE HANDLER--------------------*/
/*=================================================*/
LRESULT CALLBACK DX9::WinProc(HWND hwnd, UINT msg, WPARAM wprm, LPARAM lprm)
{
switch (msg)
{
case WM_DESTROY:
PostQuitMessage(0);
break;
}
return DefWindowProc(hwnd, msg, wprm, lprm);
}
/*=================================================*/
/*--------------END MESSAGE HANDLER----------------*/
/*=================================================*/
/*=================================================*/
/*--------------DIRECTINPUT FUNCTIONS--------------*/
/*=================================================*/
// for init only, helper function to initially acquire the
// mouse and keyboard
void DX9::AcquireInputDevice(const LPDIRECTINPUTDEVICE8& dev)
{
// loop and attempt to acquire the device until success
while (FAILED(dev->Acquire()))
{
dev->Acquire();
}
}
// update the state of the mouse and keyboard
void DX9::InputUpdate()
{
_diKeyboard->GetDeviceState(sizeof(_keys), (LPVOID)_keys);
_diMouse->GetDeviceState(sizeof(_mouseState), (LPVOID)&_mouseState);
// after directinput has been updated, check to see if any keys are no,
// longer pressed, and reset the keystate array at that key's index if,
// this is the case
// keystates true = key is available for key press
if (_keyboardStateChanged)
{
for (int i = 0; i < 256; i++)
{
if (!KeyHeld(i))
{
_keyStates[i] = true;
}
}
}
_keyboardStateChanged = false;
}
// captures a key being held down
BYTE DX9::KeyHeld(ush key)
{
return _keys[key] & 0x80;
}
// captures a single key press
bool DX9::KeyPressed(ush key)
{
if (KeyHeld(key) && _keyStates[key])
{
_keyStates[key] = false;
return true;
}
else
{
if (!KeyHeld(key) && !_keyStates[key])
{
_keyboardStateChanged = true;
}
return false;
}
}
/*=================================================*/
/*--------------END DIRECTINPUT FUNCTIONS----------*/
/*=================================================*/
/*=================================================*/
/*--------------SPRITE FUNCTIONS-------------------*/
/*=================================================*/
// returns the sprite interface
const LPD3DXSPRITE& DX9::GetSpriteInterface()
{
return _spriteBatch;
}
// begin drawing with the sprite batch
void DX9::SpriteBeginDraw(DWORD flags)
{
_spriteBatch->Begin(flags);
}
// end sprite batch drawing
void DX9::SpriteEndDraw()
{
_spriteBatch->End();
}
/*=================================================*/
/*--------------END SPRITE FUNCTIONS---------------*/
/*=================================================*/
/*=================================================*/
/*--------------FONT FUNCTIONS---------------------*/
/*=================================================*/
// create a font
void DX9::MakeFont(int height, int width, UINT weight, LPCSTR face, bool italic)
{
LPD3DXFONT newfont;
CheckHR(D3DXCreateFont(_d3ddev,
height,
width,
weight,
0,
italic,
DEFAULT_CHARSET,
OUT_DEFAULT_PRECIS,
CLEARTYPE_QUALITY,
DEFAULT_PITCH | FF_DONTCARE,
face,
&newfont));
_fonts.push_back(newfont);
}
// gets a font at the specified index
const LPD3DXFONT& DX9::GetFontAtIndex(ush index)
{
return _fonts[index];
}
const std::vector<LPD3DXFONT>& DX9::GetFontVector()
{
return _fonts;
}
/*=================================================*/
/*--------------END FONT FUNCTIONS-----------------*/
/*=================================================*/
}
#endif
This really doesn't do anything but create and initialize a window, DirectX and some basic DirectX functions.
The actual error is this:
Error 1 error LNK2005: "public: __thiscall nsdx9::DX9::DX9(struct HINSTANCE__ * &,int,class std::basic_string<char,struct std::char_traits<char>,class std::allocator<char> > const &,unsigned short,unsigned short,short,short)" (??0DX9#nsdx9##QAE#AAPAUHINSTANCE__##HABV?$basic_string#DU?$char_traits#D#std##V?$allocator#D#2##std##GGFF#Z) already defined in game_manager.obj C:\Users\JAREK\documents\visual studio 2010\Projects\example\example\main.obj
This error is repeated for every single function in dx9.h. If I ONLY include dx9.h in main.cpp, I do not get this error. It is only if I include dx9.h in any other cpp file, or use any of the parameters in dx9.h in cpp files that have access to dx9.h by being included after dx9.h in main.cpp that I get this error. This sounds confusing, so here are some samples from other parts of the program:
main.cpp:
#include "sys_params.h"
#include "dx9.h"
#include "game_manager.h"
int WINAPI WinMain (HINSTANCE inst, HINSTANCE pinst, LPSTR cmdLine, int cmdShow)
{
// state of the program
bool appEnd = false;
// create and initialize the window and directx9
nsdx9::DX9* _dx9 = new nsdx9::DX9(inst, cmdShow, nssysprms::GAME_TITLE,
nssysprms::WND_WIDTH, nssysprms::WND_HEIGHT,
nssysprms::WND_POS_X, nssysprms::WND_POS_Y);
// create and initialize the game manager
Game_Manager* _mngr = new Game_Manager(_dx9);
// Windows message handler
// also the entry point for the main game loop
while (_dx9->ProcessMessages() != WM_QUIT && !appEnd)
{
if (!_mngr->Game_Run())
{
appEnd = true;
}
}
// clean up everything
delete _mngr;
delete _dx9;
return 0;
}
game_manager.h:
#ifndef _GAME_MANAGER_H_
#define _GAME_MANAGER_H_
#include <stack>
#include <vector>
#include "dx9.h"
#include "screen.h"
#include "message_handler.h"
class Game_Manager
{
public:
Game_Manager(nsdx9::DX9* dx9);
~Game_Manager();
bool Game_Run();
private:
nsdx9::DX9* _dx9;
std::stack<Screen*> _screens;
Message_Handler* _msg_hnd;
// *** DECLARE SCREENS HERE *** //
void InitFonts();
void InitScreens();
};
#endif
This should be what is actually causing the issue. The issue is originating from main.cpp through game_manager.h. Nothing I've tried has solved the problem for me. I've included header guards in dx9.h, so I have no idea what could be causing this. if you guys need more information, please let me know. Thanks!
Your definitions of the DX9 methods (as opposed to just the class definition) seem to be in the dx9.h header file - so you violate C++'s one-definition rule when you include dx9.h in multiple .cpp files. To solve this, move the method implementations into a .cpp file (e.g. dx9.cpp).
Don't include the implementation in the header file. This causes the implementation to be compiled again everywhere it is included.
for example:
/*=================================================*/
/*--------------DIRECTX CONSTRUCTOR----------------*/
/*=================================================*/
DX9::DX9(HINSTANCE& inst, int cmdShow, const std::string& title, ush wndwidth, ush wndheight, short wndx, short wndy)
{
.... et al
put that in it's own cpp

CFileDialog :: Browse folders

When I try to instantiate a CFileDialog object it shows both the folders and files. How do you create a CFileDialog that browses for folders alone?
It is very simple, really.
Use CFolderPickerDialog which is derived from the class CFileDialog!
You can't do it with CFileDialog.
Either you will use SHBrowseForFolder Function or a wrapper for it, like CFolderDialog - Selecting Folders.
Starting from Vista it's recommended to use IFileDialog with the FOS_PICKFOLDERS option (see msdn):
CFileDialog od(TRUE/*bOpenFileDialog*/, NULL, NULL,
OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT , NULL, NULL, 0,
TRUE/*bVistaStyle*/);
IFileOpenDialog * openDlgPtr = od.GetIFileOpenDialog();
if ( openDlgPtr != NULL )
{
openDlgPtr->SetOptions(FOS_PICKFOLDERS);
openDlgPtr->Release();
}
od.DoModal();
Like someone mentioned, use CFolderPickerDialog which works great. I would like to give you example how to use it especially when using the multi select flag:
CFolderPickerDialog folderPickerDialog(initialFolder, OFN_FILEMUSTEXIST | OFN_ALLOWMULTISELECT | OFN_ENABLESIZING, this,
sizeof(OPENFILENAME));
CString folderPath;
if (folderPickerDialog.DoModal() == IDOK)
{
POSITION pos = folderPickerDialog.GetStartPosition();
while (pos)
{
folderPath = folderPickerDialog.GetNextPathName(pos);
}
}
starting from windows vista,you can use the Common Item Dialog .
void CQiliRegrvDlg::OnBnClickedSelectDir()
{
HRESULT hr = S_OK;
// Create a new common open file dialog.
IFileOpenDialog *pfd = NULL;
hr = CoCreateInstance(CLSID_FileOpenDialog, NULL, CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pfd));
if (SUCCEEDED(hr))
{
// Set the dialog as a folder picker.
DWORD dwOptions;
hr = pfd->GetOptions(&dwOptions);
if (SUCCEEDED(hr))
{
hr = pfd->SetOptions(dwOptions | FOS_PICKFOLDERS);
}
// Set the title of the dialog.
if (SUCCEEDED(hr))
{
hr = pfd->SetTitle(L"Folder");
}
// Show the open file dialog.
if (SUCCEEDED(hr))
{
hr = pfd->Show(m_hWnd);
if (SUCCEEDED(hr))
{
// Get the selection from the user.
IShellItem *psiResult = NULL;
hr = pfd->GetResult(&psiResult);
if (SUCCEEDED(hr))
{
PWSTR pszPath = NULL;
hr = psiResult->GetDisplayName(SIGDN_FILESYSPATH, &pszPath);
if (SUCCEEDED(hr))
{
m_appDir = pszPath;
SetDlgItemText(IDC_STATIC, m_appDir);
CoTaskMemFree(pszPath);
}
psiResult->Release();
}
}
}
pfd->Release();
}
}
Seems to me the answer you are asking for is inside the code of
CMFCPropertyGridFileProperty::OnClickButton(CPoint /*point*/)
of the
<Your Visual Studio installation folder>\VC\atlmfc\src\mfc\afxpropertygridctrl.cpp
file.
If you do not have access to the code, I will post the essential part of it:
CString strPath = m_varValue.bstrVal;
BOOL bUpdate = FALSE;
if (m_bIsFolder)
{
if (afxShellManager == NULL)
{
CWinAppEx* pApp = DYNAMIC_DOWNCAST(CWinAppEx, AfxGetApp());
if (pApp != NULL)
{
pApp->InitShellManager();
}
}
if (afxShellManager == NULL)
{
ASSERT(FALSE);
}
else
{
bUpdate = afxShellManager->BrowseForFolder(strPath, m_pWndList, strPath);
}
}
else
{
CFileDialog dlg(m_bOpenFileDialog, m_strDefExt, strPath, m_dwFileOpenFlags, m_strFilter, m_pWndList);
if (dlg.DoModal() == IDOK)
{
bUpdate = TRUE;
strPath = dlg.GetPathName();
}
}
As you see, Microsoft itself does not use the Cfiledialog class when wants to open a dialog for picking folders.
For using code like that, your application class MUST be derived from CWinAppEx, not CWinApp
Actually there is a way to do this - I found it in codeguru: "Selected files and folders in CFileDialog"
If you are willing to make your own implementation of CFileDialog such as:
class CMyFileDialog : public CFileDialog
You can add the following code and it should work (It is slightly different from the codeguru example):
// This code overrides the OnNotify message of the CFileDialog
// and catches the CDN_SELCHANGE, this way you can also do
// something with the selected folders.
BOOL CMyFileDialog::OnNotify(WPARAM wParam, LPARAM lParam, LRESULT* pResult)
{
NMHDR* pNotificationParam = (NMHDR*)lParam;
// Check that we got to the selection change notification.
int code = pNotificationParam->code;
if (code == CDN_SELCHANGE)
{
CStringArray theSelection;
GetListControllSelectedItems(theSelection);
// Do as you want with theSelection.
}
return CFileDialog::OnNotify(wParam, lParam, pResult);
}
// The following Code is accessing the selection in the CFileDialog
// and filling a string array with the selected names
BOOL CMyFileDialog::GetListControllSelectedItems(CStringArray& selectedItemNames)
{
BOOL rc = FALSE;
// Get the list control of the file dialog.
CWnd* pParentWnd = GetParent();
CWnd* pListControlWnd = pParentWnd->GetDlgItem(lst2);
if (pListControlWnd) {
// Get the selection from the list control.
CListCtrl* pListCtrl = (CListCtrl*)(pListControlWnd->GetDlgItem(1));
UINT selectionCount = pListCtrl->GetSelectedCount();
// When there are items selected.
if (selectionCount) {
rc = TRUE;
selectedItemNames.RemoveAll();
POSITION itemPos = pListCtrl->GetFirstSelectedItemPosition();
while (itemPos != NULL)
{
int itemNum = pListCtrl->GetNextSelectedItem(itemPos);
CString currentItemName = pListCtrl->GetItemText(itemNum, 0);
selectedItemNames.Add(currentItemName);
}
}
}
return rc;
}
Note: In CFileDialog::OnFileNameChange of the Microsoft MFC documentation they actually do hint toward this solution, but without elaborating too much.
I had a problem in my very old, legacy code, where I have a customized file dialog that actually needs to save a folder!!!
After twenty two years of hardship and pain, my code is now complete...