|
i wrote a simple game in MFC and when someone has won or lose the game i want to kill the focus and display a messagebox saying you have won/lose... can i use OnKillFocus() to do that? i did that but it will only display the messagebox when i minimize the window or point on another window. Any suggestions or anything on what am doing wrong??? ... anyways, thank your for your help in advance....
|
|
|
|
|
OnKillFocus is a handler for WM_KILLFOCUS, which is sent to a window when it loses the focus. That's why it's called when you minimise or point to another window (as your game's window loses the focus). The change the window that has the focus, use SetFocus().
If you create a message box, that will by default obtain the focus, so your game will lose it. I don't think you need to worry about focus at all in this circumstance, you just need to:
if (game_is_won)
{
MessageBox(NULL, _T("Game over, dude!"), _T("MyGame"), MB_OK);
}
------------------------
Derek Waters
derek@lj-oz.com
|
|
|
|
|
Oh, ok thank you very much Derek
|
|
|
|
|
OnKillFocus is used to perform whatever action you please when the window has lost the focus. To make a window lose its focus, set it elsewehere with SetFocus or SetForegroundWindow .
Joaquín M López Muñoz
Telefónica, Investigación y Desarrollo
|
|
|
|
|
Ok, I have been trying to get this to work for a while now. The response I got from my previous thread helped me in theory but didn't help my code.. so I'm posting a more detailed question if anyone can help me. I have a dialog based MFC app with a child listcontrol in report view. I then created another class for another window that will display another listcontrol but with the exact same column and data in it. My problem is that I can't copy the data over with what i've tried.. I have the user add item to the first list using SetItemData(). Like the following->
listitems.mask = LVIF_TEXT;
listitems.iItem = 0;
listitems.iSubItem = 0;
listitems.pszText = (LPTSTR)(LPCTSTR)(strTitle);
m_MyList.InsertItem(&listitems);
listitems.mask = LVIF_TEXT;
listitems.iSubItem = 1;
listitems.pszText = (LPTSTR)(LPCTSTR)(m_strFirstName);
m_MyList.SetItem(&listitems); ...... There are five columns
and then when the user clicks a menu item it will open up another window showing the listcontrol that is supposed to show the same data. Here is the code for that->
void CMFCDlg::OnListSortbyday()
{
DWORD_PTR tempdata = m_MyList.GetItemData(0);
GenList SortWindow;
SortWindow.m_SortList.SetItemData(0,tempdata);
SortWindow.DoModal();
}
m_MyList is a public member CListCtrl of the main window, and m_SortList is a public member CListCtrl of the newly opened window.
This is my most recent try at getting this to work... I get an assertion error when compiling though....
My previous methods were declaring m_SortList as a CListCtrl pointer and point it to m_MyList, or setting the DDX_Control of the listview to CMFCDlg::m_MyList, but neither methods worked. I'm sure there is a way to get this to work.. Maybe making an instance of my main window.. but I don't know how to do that... So can someone guide me in the right direction? I don't want to just loop through and copy every single row, but I may have to.. Please help me out with some explicit instructions and sample code. Thanks!!
Sorry for the long post..
|
|
|
|
|
Hi,
Your problem (which I assume is an assertion when running, not compiling) is that when you call SetItemData in your OnListSortByDay() function, the list control does not exist (if you look at the assertion, it will assert on (m_hWnd == NULL), ie. your control hasn't been created yet). All of the creation is done once you call DoModal. But of course, as it's modal, you can't call any subsequent functions in OnListSortByDay().
So, here's my suggestion. I'm sure other people will have others. In your GenList class, create a public function called SetCopyFromList, where you pass in a CListCtrl pointer:
void GenList::SetCopyFromList(CListCtrl *apCopyDataFrom);
In that function, store the pointer for later use in a member variable of GenList. Then, in the OnInitDialog() handler for GenList, you can use this pointer to obtain data for your list control, safe in the knowledge that m_SortList has been created.
Another alternative would be to override GenList::DoModal() with another function such as GenList::DoModal(CListCtrl *apCopyDataFrom) and then call CDialog::DoModal() inside that function.
Hope this helps.
------------------------
Derek Waters
derek@lj-oz.com
|
|
|
|
|
Great Response Derek! You are right that the assertion error is at runtime, I got confused.. This definitely put me in the right direction. However, after I copied the list through item data, nothing is showing in the newly generated list... I just added this code to test if the data are being copied in an overridden OnInitDialog function->
LVITEM tempdata;
CopiedList->GetItem(&tempdata);
m_SortedList.InsertItem(&tempdata);
No luck...
Please help me solve this final obstacle. Thanks.
|
|
|
|
|
LVITEM tempdata;
TCHAR textBuf[1024] = { 0 }; // unless your strings may be longer...
// specify which item to copy:
tempdata.iItem = <index of="" item="">;
tempdata.iSubItem = 0;
// specify which data to copy:
tempdata.mask = LVIF_IMAGE | LVIF_INDENT | LVIF_PARAM | LVIF_STATE | LVIF_TEXT;
tempdata.stateMask = -1;
tempdata.pszText = textBuf;
tempdata.cchTextMax = 1023;
CopiedList->GetItem(&tempdata);
int insertIdx = m_SortedList.InsertItem(&tempdata); // idx where item was isnerted
// also, you would need to copy sub item text manually...
for(colIdx=1 to columns) {
CString text = CopiedList->GetItemText( <index of="" item="">, colIdx);
m_SortedList.SetItemText(insertIdx, colIdx, text);
}
--------------
completely different approach:
probably it's to late to change now, but I'd used two virtual list controls for this
Instead of feeding the list control, it asks you what to display when something is to be displayed.
(However, you would need to sort the stuff yourself)
Peter
|
|
|
|
|
Well, finally got it to work just copying every item through a loop. So I guess that'll have to do for now. Thanks for everyone's help. Now I just need to figure out how to render the listview based on the data given to it.. (Don't know if that's possible..) But that's for another thread...
|
|
|
|
|
Well, I'm trying to send text to a child window. When I do FindWindow(WndClass, NULL); it doesn't like to find the chil window. I have no problem finding the main window... this is how i have it set up right now for getting the parent of the child window i want
CWnd *pMyWindow = FindWindow("AIM_IMessage", NULL);
pMyWindow->GetSafeHwnd();
if (pMyWindow == 0){
AfxMessageBox("Didnt Find IM window");
return;
}
if (pMyWindow != 0){
pMyWindow->SetWindowText("Some Text");
AfxMessageBox("Sent Text.");
return;
}
any suggestions?
|
|
|
|
|
You need to find the parent window, then use that window handle to find the child window. I would suggest something like this.
HWND hParent = FindWindow("AIM_IMessage", NULL);
if (hWnd != NULL) {
HWND hChild = FindWindowEx(hParent, NULL, "ChildWindowClassName", NULL);
if (hChild != NULL) {
::SetWindowText(hChild, "some text");
}
} else {
::MessageBox(NULL, "Could not find IM window", "Error", MB_ICONINFORMATION);
}
"Why kill time, when you can kill yourself?"
- Cabaret Voltaire
|
|
|
|
|
If destructors are called when an object goes outta scope, is the following legit:
CButton* pControls
pControls = new CButton[12];
pControls[0].Create(blah);
pControls[1].Create(blah);
pControls[n].Create(blah);
delete [] pControls;
when delete is called on the controls pointer do all the CWnd destructors get called automatically...???
Would I have to call the controls destroyWindow functions..??
Is the above acceptable or will it cause leaks...?
TIA!
"An expert is someone who has made all the mistakes in his or her field" - Niels Bohr
|
|
|
|
|
The way I understand it, anything created with new should be deleted, the destructors in CWnd will be called. Then again, I never tried what your doing. Run the app through the debugger while the app creates these controls. Then exit the app, you will see any memory leaks in the output window if any.
|
|
|
|
|
Call me lazy, but thats why I'm asking...thats why I always ask.
Learn from other peoples mistakes kinda thing...
I ain't getting memory leak detection in output window.
I'm deleting the array...this is OK...but if any of those elements are created controls...i'm curious if I have to call the DestroyWindow().
If when the array is deleted it calls all the destructors then I have nothing to worry about. This is what I don't know. Theres no leaks in the output...so I would have to reply on other tools like stress and resource meter manually watch them go up and down plus i'm super anal and would need to do it and verify about 100 times before I trusted my readings...very time consuming...
So i'm hoping someone will know for sure.
Thanx!
"An expert is someone who has made all the mistakes in his or her field" - Niels Bohr
|
|
|
|
|
Deleting the array will call the destructors on all the objects, but I have found that in the past sometimes calling delete on a window and not calling DestroyWindow first causes problems. Having said that, it must be in certain circumstances only, because DestroyWindow is not guarenteed to be called by the MFC framework on it's own windows.
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
|
|
|
|
|
Don't the CWnd destrcutors call destroywindow() automatically...??
"An expert is someone who has made all the mistakes in his or her field" - Niels Bohr
|
|
|
|
|
Not according to MSDN, DestroyWindow destroys the window the CWnd encapsulates, but not the CWnd itself.
Christian
The tragedy of cyberspace - that so much can travel so far, and yet mean so little.
|
|
|
|
|
Christian Graus wrote:
Not according to MSDN, DestroyWindow destroys the window the CWnd encapsulates, but not the CWnd itself.
In his case, when his parent window is destroyed all the child windows are destroyed too. And he calls delete to delete the CWnd object in the destructor. So things should be okay.
Nish
My most recent CP article :-
A newbie's elementary guide to spawning processes
www.busterboy.org
|
|
|
|
|
|
HockeyDude wrote:
when delete is called on the controls pointer do all the CWnd destructors get called automatically...???
Yes they will be called but IMO before that you will have to remove the windows from screen.
From MSDN:
"In the MFC framework, when the user closes the frame window, the window’s defaultOnClose handler callsDestroyWindow."
HockeyDude wrote:
Would I have to call the controls destroyWindow functions..??
From MSDN:
"Do not use the C++ delete operator to destroy a frame window or view. Instead, call the CWnd member function DestroyWindow. Frame windows, therefore, should be allocated on the heap with operator new."
Atul
|
|
|
|
|
|
Yes Nish you are correct I was talking about CButton.
I was positive that destructors were called with delete, but you and christian have helped me verify with myself.
Although what Christian said about DestroyWindow not being called kinda has me worried, i'd hate to have a bunch of HWND's lingering around after there CWnd is bye bye.
Ahh..to hell with it...i'm take the leakage if there is any...
Thanx !
"An expert is someone who has made all the mistakes in his or her field" - Niels Bohr
|
|
|
|
|
|
All I needed to hear...
Thanx Nish!
"An expert is someone who has made all the mistakes in his or her field" - Niels Bohr
|
|
|
|
|
Oops a daisy!...you are right...
Sorry...must have been daydreaming...
Atul
sleep...sleep...sleep...
|
|
|
|