Using CFolderPickerDialog for the purpose of 'Save As' (MFC) - mfc

I would like to use a CFolderPickerDialog instance for the purpose of 'Save As'.
In other words, the user will input the name of a (new) folder, which I can then create.
With the CFileDialog base class, this can be done during construction via the first input argument:
BOOL bOpenFileDialog // TRUE for FileOpen, FALSE for FileSaveAs
How can I go about achieving the same functionality for a CFolderPickerDialog instance?

You can not achieve this with CFolderPickerDialog as per my understanding.
Le me explain you this. Base class of CFolderPickerDialog is CFileDialog and bOpenFileDialog the flag which will allow you to launch file dialog as open or save.
Since, CFolderPickerDialog is child class hence microsoft has to provide call to parent (CFileDialog) in constructor. If you open dlgfile.cpp from ..\Microsoft Visual Studio 14.0\VC\atlmfc\src\mfc\ then you will get source code of CFolderPickerDialog class.
Now coming to point, if you observe the constructor of CFolderPickerDialog then you get exact reason why its not possible.
////////////////////////////////////////////////////////////////////////////
// Folder Picker common dialog helper
CFolderPickerDialog::CFolderPickerDialog(LPCTSTR lpszFolder, DWORD dwFlags, CWnd* pParentWnd, DWORD dwSize, BOOL fNonFileSystemFolders) :
CFileDialog(TRUE, NULL, lpszFolder, dwFlags, NULL, pParentWnd, dwSize, TRUE)
{
m_bPickFoldersMode = TRUE;
m_bPickNonFileSysFoldersMode = fNonFileSystemFolders;
}
First flag is always true that indicate unfortunately, CFolderPickerDialog will open in File Open mode only.

Related

CWindowImpl - Create() returns error code 1406

I just tried to setup a small win32 project, and was just about to create a window.
I created a dialog in the resource designer and set up this class for my window:
#pragma once
#include "stdafx.h"
class TTTMainDialog : public CWindowImpl<TTTMainDialog>
{
public:
DECLARE_WND_CLASS(_T("TTTDlg"))
enum { IDD = IDD_TTT_DIALOG };
BEGIN_MSG_MAP_EX(MusicPlayerDialog)
MSG_WM_INITDIALOG(OnInitDialog);
MSG_WM_CLOSE(OnClose);
MSG_WM_DESTROY(OnDestroy);
END_MSG_MAP()
TTTMainDialog();
~TTTMainDialog();
private:
const BOOL OnInitDialog(const CWindow wndFocus, const LPARAM lInitParam);
void OnClose();
void OnDestroy();
};
As you can see, I added the window class declaration, I inherited CWindowImpl, I registered the dialog. I don't think I forgot something here.
In the class which is supposed to create the dialog, I tried to create it like this:
TTTMainDialog myDialog;
HWND handle = myDialog.Create(NULL);
myDialog.ShowWindow(nCmdShow);
However, the Create method does return NULL all the time. I checked the error code with GetLastError(), and it turns out i am getting error code 1406, or "ERROR_TLW_WITH_WSCHILD".
The msdn documentation says the following about this error:
"Cannot create a top-level child window."
I tried to google up on this, but there is not much to find.
If I had to take a guess I would say the problem is caused by some window class name details, but i'm really not sure.
Any advice?
You are trying to build a window class from wrong pieces.
The error is pretty descriptive: you are trying to create a parentless window with a WS_CHILD style and this does not work out.
You get the child style from default template parameter: CWindowImpl -> CWindowImplBaseT -> TWinTraits -> CControlWinTraits. CControlWinTraits is supposed for use with child control windows.
If you are going to use a dialog template (IDD_TTT_DIALOG) then the proper base class is CDialogImpl, which is already prepared to use proper window styles. Also, it has what it takes to create both modal and modeless dialogs. The latter act more like windows and are non-blocking but in the same time take dialog template resource with predefined controls.
Small example for CDialogImpl use
Or, another one

How to create a notification balloon on Windows?

I want to create a simple command line tool to post quick notifications like this.
I want the tool to be as simple and small as possible. So I choose to code in CPP, and use Win32 API directly.
I found this guide very useful. But it seems this Shell_NotifyIcon API requires a valid hWnd handler, which means I will have to create a hidden/invisible window in my command line tool, which I'd rather not.
Any better idea on how to create a notification on Windows?
The shell notification API requires that you supply a window handle. So create a message only window and use that as the owner of the notification icon and balloons.
That you would prefer not to create a window in your console app is understandable but the API is what it is. You don't get to re-write system APIs for your convenience. You just have to go along with them.
You can do that easily with no need to use ATL or MFC, just pure Win32 API, which can be a Console application as well.
First you need the icon image. Store it in your resource.h file
#define IDI_BATTERY_IMAGE 101
add an .rc file to your project with the following line
IDI_BATTERY_IMAGE ICON "Battery.ico"
Bonus tip: you can find free images to download, like this one. Just make sure to call it "Battery.ico" and place it in the path of your other source files.
Best if you create a separate pair of .cpp and .h files for the notification balloon functionality.
In your .cpp file place the following code:
// tray icon data
NOTIFYICONDATA m_NID;
BOOL CreateTrayIcon()
{
memset(&m_NID, 0, sizeof(m_NID));
m_NID.cbSize = sizeof(m_NID);
m_NID.uID = IDI_BATTERY_IMAGE;
// set handle to the window that receives tray icon notifications
m_NID.hWnd = GetForegroundWindow();
// fields that are being set when adding tray icon
m_NID.uFlags = NIF_MESSAGE | NIF_ICON;
// set image
m_NID.hIcon = LoadIcon(NULL,MAKEINTRESOURCE(IDI_BATTERY_IMAGE));
if (!m_NID.hIcon)
return FALSE;
m_NID.uVersion = NOTIFYICON_VERSION_4;
if (!Shell_NotifyIcon(NIM_ADD, &m_NID))
return FALSE;
return Shell_NotifyIcon(NIM_SETVERSION, &m_NID);
}
BOOL ShowTrayIconBalloon(LPCTSTR pszTitle, LPCTSTR pszText, UINT unTimeout, DWORD dwInfoFlags)
{
m_NID.uFlags |= NIF_INFO;
m_NID.uTimeout = unTimeout;
m_NID.dwInfoFlags = dwInfoFlags;
if (StringCchCopy(m_NID.szInfoTitle, sizeof(m_NID.szInfoTitle), pszTitle) != S_OK)
return FALSE;
if (StringCchCopy(m_NID.szInfo, sizeof(m_NID.szInfo), pszText) != S_OK)
return FALSE;
return Shell_NotifyIcon(NIM_MODIFY, &m_NID);
}
In your header file place the following:
BOOL CreateTrayIcon();
BOOL ShowTrayIconBalloon(LPCTSTR pszTitle, LPCTSTR pszText, UINT unTimeout, DWORD dwInfoFlags);
In your main function add the following code:
CreateTrayIcon();
ShowTrayIconBalloon(L"27 percent remaining", L"Your battary has such and such percentage...", 1000, NULL);
The following code was tested with a simple Console app.

FindWindow by class name not working?

To preface we have a strange requirement that all dialogs must be modeless for an MFC application. There is a particular dialog using region drawing and some custom controls to select dates and times for viewing past and future data per view. I need to be able to close this window when it loses focus, the main app gets a system command, etc.
I figured the easiest way to do this would be to register the class like so:
// for CWnd::FindWindow
WNDCLASS wndcls;
SecureZeroMemory(&wndcls, sizeof(WNDCLASS));
wndcls.lpszClassName = L"CTransactionDialog";
wndcls.style = CS_HREDRAW | CS_VREDRAW;
wndcls.lpfnWndProc = AfxWndProc;
wndcls.cbClsExtra = wndcls.cbWndExtra = 0;
wndcls.hInstance = AfxGetInstanceHandle();
wndcls.hIcon = NULL;
#ifndef _WIN32_WCE_NO_CURSOR
wndcls.hCursor = AfxGetApp()->LoadStandardCursor(IDC_ARROW);
#else
wndcls.hCursor = 0;
#endif
wndcls.hbrBackground = (HBRUSH) (COLOR_BACKGROUND + 1);
wndcls.lpszMenuName = NULL;
BOOL retVal = AfxRegisterClass(&wndcls);
if (!retVal)
AfxMessageBox(L"AfxRegisterClass(CTransactionDialog) Failed");
Then later in response to various event handlers and messages where I would want these modeless window or windows to be closed to do something simple like this:
CWnd* pFound = NULL;
while ((pFound = CWnd::FindWindow(L"CTransactionDialog", NULL)) != NULL)
pFound->DestroyWindow();
However despite the registration of the class succeeding and looking at GetRuntimeClass of the dialog in question in debug and seeing that is matches up as expected the FindWindow never seems to find or close these modeless dialogs as expected.
What am I doing wrong or is there a better way to go about this?
Update: This is how the dialog is created via a static method on the dialog class. The dialog resource for the id specified in create has the Popup property set which should resolve to WS_POPUP style under the MFC covers. The dialog shouldn't and doesn't have a parent as far as I knew.
CTransactionDialog* CTransactionDialog::ShowTransactionDialog(const CRect& crCtrlToFloatAbove, UINT dialogID, Itime defaultTime, Itime initialTime)
{
CTransactionDialog* pCTDialog = new CTransactionDialog(crCtrlToFloatAbove, dialogID, defaultTime, initialTime);
pCTDialog->Create(CTransactionDialog::IDD);
pCTDialog->ShowWindow(SW_SHOW);
return pCTDialog;
}
Update: Doh! FindWindowEx isn't finding anything either.
CWnd::FindWindowEx(AfxGetMainWnd()->GetSafeHwnd(), NULL, L"CTransactionDialog", NULL);
However I have a new plan. I'm just going to make my own window message and handle it on the main frame. I think I can get away with passing a pointer to the dialog as the lParam of the message and then casting it to a CWnd* then calling DestroyWindow. It will work for most cases in a very round about way. I may run into trouble with minimizing and maximizing of the main frame window for dialogs that nothing is holding a pointer too but we'll see.
FindWindow doesn't work with child windows. To find a child window, you can use FindWindowEx, passing the HWND of the parent window as the first parameter.
Class name denotes NOT the c++ class name - it denotes the window class name. This name was used to register the window by the OS and has nothing to do with the c++ class.
May MSDN enlight you...
CWnd::FindWindow does not search child windows.
Is it possible that the mode less window that you are creating has a parent set and that is the reason why FindWindow doesn't find it ?
Below is the simplest and cleanest solution I could come up with:
BOOL CTransactionDialog::OnNcActivate(BOOL bActive)
{
if (!bActive)
PostMessage(WM_CLOSE);
return CDialog::OnNcActivate(bActive);
}
Not 100% sure about this but I think you need to set your class name in the resource file. You are defining a windows class and creating a dialog class but you aren't linking them. Setting a class name in the WNDCLASS struct won't help unless you actually have a way of linking it to the dialog. If you use the resource file and define the dialog, and class name in there then it should work.

DoModal() asserts at very first line

I have an MFC dialog based application created inside Visual Studio 2008.
CCalendarWindowDlg dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
When I run the application, DoModal() asserts at very first line
INT_PTR CDialog::DoModal()
{
// can be constructed with a resource template or InitModalIndirect
ASSERT(m_lpszTemplateName != NULL || m_hDialogTemplate != NULL ||
m_lpDialogTemplate != NULL);
}
Can anyone please help?
For solving this in the Constructor of my Dialog class, I did something like
CCalendarWindowDlg::CCalendarWindowDlg ()
:CDialog(IDD)
{
}
Notice I am calling the constructor of the CDialog parent class with the resource ID of the form I want to present.
Seems like the resource template is missing or wrongly mapped.
Look at the IDD attribute at your CCalendarWindowDlg class and see whether you have the appropriate dialog present in the Resource View.
Are you using the satellite DLLs for localization or other purpose? or the CCalendarWindowDlg component resource DLL might be missing.
I had the same problem when just creating new dialog based MFC application using Visual Studio 2012. For me the solution was to use dialog construtor that takes dialog resource ID as parameter.
For instance:
CCalendarWindowDlg dlg(IDD_MYDIALOG);
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
Hope this helps.

Using an ocx in a console application

I want to quickly test an ocx. How do I drop that ocx in a console application. I have found some tutorials in CodeProject and but are incomplete.
Isn't an OCX an ActiveX User Control? (something that you put onto a form for the user to interact with)?
The easiest way I know of to test COM/ActiveX stuff is to use excel. (Yes I know it sounds dumb, bear with me)
Run Excel, create a new file if it hasn't done this for you
Press Alt+F11 to launch the Visual Basic Editor (if you have excel 2007 it's on the 'Developer' ribbon tab thing
Now that you're in happy visual basic land...
From the Tools menu, select References
Select your OCX/COM object from the list, or click Browse... to find the file if it's not registered with COM - You may be able to skip this step if your OCX is already registered.
From the Insert menu, select UserForm
In the floating Toolbox window, right click and select Additional Controls
Find your OCX in the list and tick it
You can then drag your OCX from the toolbox onto the userform
From the Run menu, run it.
Test your OCX and play around with it.
SAVE THE EXCEL FILE so you don't have to repeat these steps every time.
Sure..it's pretty easy. Here's a fun app I threw together. I'm assuming you have Visual C++.
Save to test.cpp and compile: cl.exe /EHsc test.cpp
To test with your OCX you'll need to either #import the typelib and use it's CLSID (or just hard-code the CLSID) in the CoCreateInstance call. Using #import will also help define any custom interfaces you might need.
#include "windows.h"
#include "shobjidl.h"
#include "atlbase.h"
//
// compile with: cl /EHsc test.cpp
//
// A fun little program to demonstrate creating an OCX.
// (CLSID_TaskbarList in this case)
//
BOOL CALLBACK RemoveFromTaskbarProc( HWND hwnd, LPARAM lParam )
{
ITaskbarList* ptbl = (ITaskbarList*)lParam;
ptbl->DeleteTab(hwnd);
return TRUE;
}
void HideTaskWindows(ITaskbarList* ptbl)
{
EnumWindows( RemoveFromTaskbarProc, (LPARAM) ptbl);
}
// ============
BOOL CALLBACK AddToTaskbarProc( HWND hwnd, LPARAM lParam )
{
ITaskbarList* ptbl = (ITaskbarList*)lParam;
ptbl->AddTab(hwnd);
return TRUE;// continue enumerating
}
void ShowTaskWindows(ITaskbarList* ptbl)
{
if (!EnumWindows( AddToTaskbarProc, (LPARAM) ptbl))
throw "Unable to enum windows in ShowTaskWindows";
}
// ============
int main(int, char**)
{
CoInitialize(0);
try {
CComPtr<IUnknown> pUnk;
if (FAILED(CoCreateInstance(CLSID_TaskbarList, NULL, CLSCTX_INPROC_SERVER|CLSCTX_LOCAL_SERVER, IID_IUnknown, (void**) &pUnk)))
throw "Unabled to create CLSID_TaskbarList";
// Do something with the object...
CComQIPtr<ITaskbarList> ptbl = pUnk;
if (ptbl)
ptbl->HrInit();
HideTaskWindows(ptbl);
MessageBox( GetDesktopWindow(), _T("Check out the task bar!"), _T("StackOverflow FTW"), MB_OK);
ShowTaskWindows(ptbl);
}
catch( TCHAR * msg ) {
MessageBox( GetDesktopWindow(), msg, _T("Error"), MB_OK);
}
CoUninitialize();
return 0;
}
#orion thats so cool. Never thought of it that way.
Well #jschroedl thats was fun indeed.
Testing an activex in console app is fun. But I think its worth not trying down that path. You can call the methods or set and get the properties either through the way #jschroedl had explained or you can call the IDIspatch object through the Invoke function.
The first step is to GetIDsByName and call the function through Invoke and parameters to the function should be an array of VARIANTS in the Invoke formal parameter list.
All is fine and dandy. But once you get to events its downhill from there. Windows application requires a message pump to fire events. On a console you don't have one. I went down the path to implement a EventNotifier for the events just like you implement a CallBack interface in classic C++ way. But the events doesn't get to your implemented interface.
I am pretty sure this cannot be done on a console application. But I am really hoping someone out there will have a different take on events in a console application