Avoid MessageBox while closing child window - visual-c++

I am having a child window derived from CFormView. On certain condition in OnCreate() function, I want to close this window.
I tried 2 options:
int CFilterWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CFormView::OnCreate(lpCreateStruct) == -1)
return -1;
//Trial-1
if (!IsInitialized())
{
DestroyWindow();
return 0;
}
//Trial-2
if (!IsInitialized())
{
return -1;
}
return 0;
}
In both scenarios, the window is closed but my system returns "Failed to create empty document."
How do I avoid this message?

This is a completely normal behavior.
Document, Frame and View are created in one turn. First the document is created, than the frame and than the inner view. If one of the operations failed all other are also rolled back and fail.
So in the case of the MDI OnFileNew calls OpenDocumentFile from you template.
This function creates the new CDocument, followed by a new frame window. The frame window creates the view. This fails due to your code.
Your error message comes from CMultiDocTemplate::OpenDocumentFile because CreateNewFrame fails.
Let the MFC create your window and destroy the view it in OnInitialUpdate. This should work without this message.

Related

CDocTemplate and m_templateList

I am upgrading some software from 16 bit to 32 bit in VC++ using MFC, and I understand that in recent versions of MFC I can no longer access m_templateList in CDocTemplate, I must use GetFirstDocTemplatePosition and GetNextDocTemplate instead. That is no problem as far as enumerating templates is concerned (a dialog being opened only in the case where there is more than one template). My question is what approach is best to get round the fact that a reference to the template list is currently being passed to the dialog on creation, and a selected template is being returned? Here is the code:
void CMtApp::OnFileNew()
{
CString s;
if (m_templateList.IsEmpty())
{
TRACE0("Error : no document templates registered with CWinApp\n");
AfxMessageBox(AFX_IDP_FAILED_TO_CREATE_DOC);
return;
}
CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetHead();
if (m_templateList.GetCount() > 1)
{
// more than one document template to choose from
// bring up dialog prompting user
COpenTypeDlg dlg(&m_templateList);
if (dlg.DoModal() != IDOK)
return; // none - cancel operation
pTemplate = dlg.m_pSelectedTemplate;
pTemplate->GetDocString(s, CDocTemplate::docName);
}
ASSERT(pTemplate != NULL);
ASSERT(pTemplate->IsKindOf(RUNTIME_CLASS(CDocTemplate)));
m_bNew = TRUE;
pTemplate->OpenDocumentFile(NULL);
}
You can pass the CWinApp to the dialog's ctor and the dialog can GetFirstDocTemplatePosition and GetNextDocTemplate itself. But you don't really need to pass the CWinApp because the dialog can use AfxGetApp to get it itself.
If you insist on passing a template list then build your own list based on what GetFirstDocTemplatePosition and GetNextDocTemplate return.

Multithreading in flex web application

I am working on web application. In which i am stuck with some issue.
When i call some server function it will take time to get response. When response have high number of data. It will get data, process on that data and update GUI in background.
Upto that my application GUI freeze. I can not click on any part. I see some where that ActionScript support multithreading. I found some tutorial for that which is here. But, it is for desktop application only.
Is there any way i can handle this freezing of application/GUI in web application. It will decrease my application performance and looks very bad.
Example:
If i have list of data with checkbox and on checkbox click there is some process. Now, there is one button called "Select All". Now, if i click on "select all" then all check box selected and process on check selection is going and freeze the application upto process done.
like: I have following list
<s:List id="tempList" itemRenderer="CustomItemRenderer"
dataProvider="{someList}" useVirtualLayout="false"/>
ItemRenderer have label and checkbox as following.
<s:CheckBox id="cCheckId" selected="{data.selected}"
change="onChangeHandler(event)" />
<s:Label id="lblTest" />
protected function onChangeHandler(event:Event):void
{
data.selected = !data.selected;
}
Now, on button Select all will select all check box.
<s:Button id="btnSelectAll" label="Select All" click="selectAllHandler(event)" />
protected function selectAllHandler(event:MouseEvent):void
{
for(var i:int = 0;i<someList.length;i++)
{
someList[i].selected = true;
}
}
Now, if someList have lots of data then it will freeze the screen.
Any help is greatly appreciated.
The main idea behind the list and itemrenderers that you have a list (or datagrid) that displays like 30 items and then you can scroll to see the rest. Then you will only have 30 Itemrenderers that would be updated at once.
If you don't want to scroll you will need to distribute your item selection over several frames, something like that (untested, but you get the idea)
private static const ITEMS_AT_ONCE:int = 5000;
private var _currentIndex:int;
protected function selectAllHandler(event:MouseEvent):void
{
_currentIndex = 0;
addEventListener(Event.ENTER_FRAME, onEnterFrame); // this will call the onEnterFrame method on each frame rendered
}
private function onEnterFrame(e:Event):void
{
// make sure we don't run out of bounds of the dataprovider's length
var maxIndex:int = Math.min(_currentIndex + ITEMS_AT_ONCE, someList.length);
// set selection for the current bunch
for (var i:int = _currentIndex; i < maxIndex; i++)
{
someList[i].selected = true;
}
if (maxIndex == someList.length)
{
// We are done, remove enterframe listener
removeEventListener(Event.ENTER_FRAME, onEnterFrame);
// I'm not sure but don't you need to refresh the dataprovider to reflect the changes in the ItemRenderers ?
// (someList.dataProvider as ArrayCollection).refresh();
}
else
{
// update the _currentindex so we continue after this item on the next frame
_currentIndex = maxIndex;
}
Another possible solution - if you display all of them anyways - you might try to switch to a VGroup that will hold custom UIComponents (without MXML) for the items - this should speed up the rendering.

Get dialog window handler

I have MFC dialog based window application. Main dialog form creation is shown in code below. I have some code that runs on separate thread and sometimes I need to send message to dialog window. For this I need window handler.
Line MyAppDlg.GetSafeHwnd() returns 0. Why ? How to get dialog window handler?
BOOL CMyApp::InitInstance()
{
CWinApp::InitInstance();
// Activate "Windows Native" visual manager for enabling themes in MFC controls
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
startAll(NULL);
CMyAppDlg MyAppDlg;
m_pMainWnd = &MyAppDlg;
m_pActiveWnd = &MyAppDlg;
AuthMsgHWND = MyAppDlg.GetSafeHwnd();
INT_PTR nResponse = MyAppDlg.DoModal();
if (nResponse == IDOK)
{
// TODO: Place code here to handle when the dialog is
// dismissed with OK
}
else if (nResponse == IDCANCEL)
{
// TODO: Place code here to handle when the dialog is
// dismissed with Cancel
}
else if (nResponse == -1)
{
TRACE(traceAppMsg, 0, "Warning: dialog creation failed, so application is terminating unexpectedly.\n");
TRACE(traceAppMsg, 0, "Warning: if you are using MFC controls on the dialog, you cannot #define _AFX_NO_MFC_CONTROLS_IN_DIALOGS.\n");
}
// Since the dialog has been closed, return FALSE so that we exit the
// application, rather than start the application's message pump.
return FALSE;
}
The dialog object has been created but the dialog window (and its HWND) are not created until after DoModal is called. The first place you can get access to this HWND is in the dialog's OnInitDialog function.
You've tried to get the HWND of the object before the dialog has been created with DoModal - that won't work. And since DoModal won't return until the dialog has been destroyed, you can't do it after. You'll have to find another point where you can capture that handle.
P.S. Don't call SendMessage from another thread. You're asking for trouble. Use PostMessage instead.

Create Property Sheet in Frame Window

I am using an MDI application. I want to create a property sheet inside Frame Window area as shown by arrow in image below:
I have seen examples where we can use ShowWindow() function after creating property sheet but it creates property sheet which is not embedded in frame window.
Can we create propertysheet on frame window only like other controls as static box etc?
If you need to embed a resizable property sheet to the view, please take a look at BCGSoft size(http://www.bcgsoft.com) - the latest BCGControlBar from version shows how to do it:
http://www.bcgsoft.com/images/resizableform220.jpg
If you simply need a tabbed MDI windows, just create a Visual Studio-like application in MFC AppWizard (VS 2008 or later).
Hope, this helps.
Rob
Adding CMultiDocTemplate instances solved my problem. Here is code snippet. This is part of ProjectName.cpp file:
BOOL CEmuDiagnosticsClientApp::InitInstance()
{
// InitCommonControlsEx() is required on Windows XP if an application
// manifest specifies use of ComCtl32.dll version 6 or later to enable
// visual styles. Otherwise, any window creation will fail.
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// Set this to include all the common control classes you want to use
// in your application.
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinAppEx::InitInstance();
// Initialize OLE libraries
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
//Added new code
{
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_STRING_LOGGINGWINDOW,
RUNTIME_CLASS(CEmuDiagnosticsClientDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CLoggingWindow));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
}
//End: Added new code
// Standard initialization
// If you are not using these features and wish to reduce the size
// of your final executable, you should remove from the following
// the specific initialization routines you do not need
// Change the registry key under which our settings are stored
// TODO: You should modify this string to be something appropriate
// such as the name of your company or organization
SetRegistryKey(_T("Local AppWizard-Generated Applications"));
LoadStdProfileSettings(4); // Load standard INI file options (including MRU)
InitContextMenuManager();
InitKeyboardManager();
InitTooltipManager();
CMFCToolTipInfo ttParams;
ttParams.m_bVislManagerTheme = TRUE;
theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views
CMultiDocTemplate* pDocTemplate;
pDocTemplate = new CMultiDocTemplate(IDR_STRING_SIGNALWINDOW,
RUNTIME_CLASS(CEmuDiagnosticsClientDoc),
RUNTIME_CLASS(CChildFrame), // custom MDI child frame
RUNTIME_CLASS(CSignalWindow)); //Changed Code
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// create main MDI Frame window
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
{
delete pMainFrame;
return FALSE;
}
m_pMainWnd = pMainFrame;
// call DragAcceptFiles only if there's a suffix
// In an MDI app, this should occur immediately after setting m_pMainWnd
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line. Will return FALSE if
// app was launched with /RegServer, /Register, /Unregserver or /Unregister.
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The main window has been initialized, so show and update it
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
return TRUE;
}
In //Added New code section, created a new CMultiDocTemplate instance. CLoggingWindow is the class which I wanted to display in frame window.
Another class CSignalWindow I also wanted to display which is modified in //changed code area.
Things to remember:
-Dialog which you want to display must be derived from CFormView, not CDialog.
-Changed dialog property: Border -> None, Style -> Child and all other properties to false.

Implementing a blocking modal view/dialog like in Windows Forms - is it possible?

In short:
I want to show a view or action sheet and only continue code execution after the user has dismissed the view / sheet. So: line one shows the view, line two reads some result variable.
In detail why I would need this:
I'm porting a Windows Forms application over to the iPad. The original implementation has a communication class which uses a web service to communicate with the server. It offers a couple of methods to get data. Conveniently it checks prior to each call if the user still has a valid connection or if he has to re-enter his password for security reasons.
If the password is required, the .NET class shows a modal dialog which blocks any further code executio and if the password was entered, retries the last call it has made before showing the dialog.
Now using CocoaTouch I'm facing a problem. I replaced the code that shows the dialog with a UIActionSheet. Works great but code execution continues immediately, whereas in Windows Forms it is blocked (the next line in Windows Forms after showing the dialogs is to read the entered password from the dialog) until the dialog has been closed.
I tried a Thread.Sleep() until the user dismisses the UIActionSheet but the Thread.Sleep() also blocks the main loop and my view won't even be drawn.
The alternative I currently see is to change all methods in the already working class and give them a return value: if password required, handle it, then retry.
But this means that all over my code I will have to add these checks because at any given moment the password might be needed. That's why it is nested in communication class in Windows Forms.
Any other ideas?
René
Yes, it is possible.
To do this, what you can do is to run the mainloop manually. I have not managed to stop the mainloop directly, so I instead run the mainloop for 0.5 seconds and wait until the user responds.
The following function shows how you could implement a modal query with the above approach:
int WaitForClick ()
{
int clicked = -1;
var x = new UIAlertView ("Title", "Message", null, "Cancel", "OK", "Perhaps");
x.Show ();
bool done = false;
x.Clicked += (sender, buttonArgs) => {
Console.WriteLine ("User clicked on {0}", buttonArgs.ButtonIndex);
clicked = buttonArgs.ButtonIndex;
};
while (clicked == -1){
NSRunLoop.Current.RunUntil (NSDate.FromTimeIntervalSinceNow (0.5));
Console.WriteLine ("Waiting for another 0.5 seconds");
}
Console.WriteLine ("The user clicked {0}", clicked);
return clicked;
}
I think this approach using async/await is much better, and doesn't suffer from freezing the app when rotating the device, or when the autoscrolling interferes and leaves you stuck in the RunUntil loop forever without the ability to click a button (at least these problems are easy to reproduce on iOS7).
Modal UIAlertView
Task<int> ShowModalAletViewAsync (string title, string message, params string[] buttons)
{
var alertView = new UIAlertView (title, message, null, null, buttons);
alertView.Show ();
var tsc = new TaskCompletionSource<int> ();
alertView.Clicked += (sender, buttonArgs) => {
Console.WriteLine ("User clicked on {0}", buttonArgs.ButtonIndex);
tsc.TrySetResult(buttonArgs.ButtonIndex);
};
return tsc.Task;
}

Resources