|
After the process is created, you can use pProcessInfo and OpenProcess to obtain a handle to the running process (pProcessInfo.hProcess ). Giving this handle to TerminateProcess will instantly kill the running application. Note that this is the same thing as using CTRL+ALT+DEL on a Windows XP machine: the target process is not notified that it is closing, but is terminated instantly. If you're operating on a Word document to which the user can read, write and save, then using TerminateProcess is a sure way to lose all unsaved work. It will not ask questions or confirmations: it will just kill the process, straight through.
After the process is terminated, GetExitCodeProcess will return the exit code with which the primary thread of the application exited.
Is this what you asked for ?
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Yes, TerminateProcess is what I need to exit the process unconditionally. What I'm really trying to do is parse a word document and pass the values to another child MDI Window for display. The word document gets parsed and opened for viewing via CreateProcess.
Now if the child window was closed and needs to be viewed once again, the user must select that same word document to be re-parsed. It can't parse it when it's already open so I need to close that document and then reopen it for the parsing to work. How can I keep track of all of the word documents that are currently open so that I can close them for re-parsing?
|
|
|
|
|
Hey all, I am having a problem when given a CTempWnd pointer to a deleted window.
I have developed CButton derived class that is supposed to, when clicked, return the input focus to the window that had it before it was clicked. I do this by saving the HWND of the window that is passed into the OnSetFocus() function, and set the focus back to it in the BN_CLICKED message handler.
void COneClickButton::OnSetFocus(CWnd *pOldWnd)
{
CButton::OnSetFocus(pOldWnd);
COneClickButton *pOCB = dynamic_cast<COneClickButton *>(pOldWnd);
m_hFocusFromWnd = *pOCB ? pOCB->m_hFocusFromWnd : *pOldWnd;
}
BOOL COneClickButton::OnClicked()
{
if (IsWindow(m_hFocusFromWnd))
::SetFocus(m_hFocusFromWnd);
else
GetParent()->SetFocus();
return FALSE;
} Ok, that was the easy part. Now comes the fun part that I am having a problem with.
I am using Chris's MFCGrid on a CPropertyPage, with several COneClickButton buttons on the property sheet. The problem comes when the user is editing a cell on the grid and then clicks one of the buttons while the edit window is still open. The CInPlaceEdit class that the grid uses for editing has a feature where by it closes and deletes itself as soon as it loses the input focus, which is all fine and well. But now, when the COneClickButton gets the focus, the pOldWnd pointer points to a now invalid window and the button has no idea where to return the focus. Currently I just set the focus to the property sheet, which passes the focus to the first control on the page. I want the focus to go back to the MFCGrid.
Anybody have any ideas on how to accomplish this, short of handling WM_SETFOCUS messages for every control in my app?
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04
Within you lies the power for good - Use it!
|
|
|
|
|
The answer is inside the CPropertyPage . This class is derived from CDialog and onwards from CWnd . This inheritance chain will allow access to the GetDlgItem function. Using this function can return a pointer to the requested dialog control's CWnd parent class.
As you are coding the property page, you also have access to the ID specified to the MFCGrid. Thus, you can use GetDlgItem to obtain the CWnd -pointer and call CWnd::SetFocus to set the input focus to the grid. All this should be done only if the handle to the old window is no longer valid (in place of GetParent()->SetFocus() ).
Does this solve it ?
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Antti Keskinen wrote:
Does this solve it ?
Yes and no. It sounds like it will work, I will give it try. But it is not very OOP. It will require the COneClickButton knowing all about the property sheet it is on, the pages that are on the sheet, and the grids that are on the pages. I was hoping to there was a way that it could be done without the COneClickButton knowing all that stuff.
Thanks for the pointer, I am now further along then I was before.
"You're obviously a superstar." - Christian Graus about me - 12 Feb '03
"Obviously ??? You're definitely a superstar!!!" mYkel - 21 Jun '04
Within you lies the power for good - Use it!
|
|
|
|
|
If you had a normal Windows control, it would always have the HWND of the parent window. Thus, getting this HWND and enumerating the child windows would return the control itself at some point.
The COneClickButton is a similar case: it is an MFC control (I presume), thus it needs to be derived from CWnd. In this case, it has the GetParent function, which allows it to get a pointer to the parent's CWnd class.
The most object-oriented way (I think) would be to first use GetParent to get the parent window (property page) and then use EnumChildWindows to query through all children of this page, looking for one which has the same class name as the grid control.
I don't think there is a more object oriented way than that without breaking the way Windows works.. Or at least, I'm not aware of one if there is..
-Antti Keskinen
----------------------------------------------
The definition of impossible is strictly dependant
on what we think is possible.
|
|
|
|
|
Hello,
I am developing a database application. The database will be on a server, but I would like to be able to allow viewing and editing while not on the network. Lotus Notes does this, and probably other applications.
Any suggestions as to how to implement this? Should I keep a record of all changes to individual fields and records as the user makes changes and then process them onto the network database when the user is connected again?
Regards,
Ted
|
|
|
|
|
|
Hi, I have two windows processes and one sends (posts) a mesage to the other to activate it etc. When the main app gets this message it calls SetForegroundWindow() to bring the app to the foreground so it is the active/on top application.
The problem is SetForegroundWindow() is failing (returning 0) and my app stays in the background. I've also tried BringWindowToTop().
The WinXP Task Bar flashes the Icon for my app.
I'm going nuts here.
Neville Franks, Author of ED for Windows www.getsoft.com and coming soon: Surfulater www.surfulater.com
|
|
|
|
|
That's how XP works. It flashes the taskbar instead of having the application take over the screen. If you can, try your App. on a Win 98 machine just to make sure it's XP and not your code.
|
|
|
|
|
|
|
Well my initial hopes have been dashed. It appears to work when I run the App in the Debugger, but not otherwise.
I think the problem is the first app is stealing back or not relinquishing focus. I have another path I'm about to head down.
I use SetForegroundWindow() at other times in the App to restore from the System Tray for example and they work fine.
Neville Franks, Author of ED for Windows www.getsoft.com and coming soon: Surfulater www.surfulater.com
|
|
|
|
|
|
Hi Scott,
Thanks for that. I'd never heard of SwitchToThisWindow().
This sort of works, however there are two problems. First the Task Bar pops-up (I have it to Auto-Hide) and flashes the app icon. Second and worse is if I Alt+Tab to another app afer my app has come to the foreground using SwitchToThisWindow() then cause my app to activate using SwitchToThisWindow() the aforementioned app is activated not mine. This is a killer.
Finally SwitchToThisWindow sends the previous app to the bottom of the Z-Order which seems very strange. AFAIK this isn't what SetForegroundWindow() does.
I can't believe something as simple as this is causing me so much grief.
Neville Franks, Author of ED for Windows www.getsoft.com and coming soon: Surfulater www.surfulater.com
|
|
|
|
|
As others have said this is the way XP is supposed to work; users don't like have the rug window they are working in being pulled away without warning. However, if you are certain you have a really good reason to do it (warning of an impending nuclear strike or the re-election of Dubbya), you can (usually) do it this way:
BOOL StealFocus(CWnd *pWnd)
{
DWORD ForeGroundID = GetWindowThreadProcessId(::GetForegroundWindow(), NULL);
DWORD CurrentID = GetCurrentThreadId();
BOOL bRet = AttachThreadInput(ForeGroundID, CurrentID, TRUE);
pWnd->SetForegroundWindow();
pWnd->SetFocus();
AttachThreadInput(ForeGroundID, CurrentID, FALSE);
return bRet;
}
The opinions expressed in this communication do not necessarily represent those of the author (especially if you find them impolite, discourteous or inflammatory).
|
|
|
|
|
Hi Phil,
Thanks for the reply. I couldn't get this to work reliably either as indicated in an earlier reply. It worked in the debugger, but not outside.
Both of these apps are mine, so I just need the ability to get one to bring the other to the foreground. I've read up on all the issues and what MS is trying to do and why and I'm basically ok with that. But in my case I'm not pulling any rugs out from under anyone but myself.;)
I have a solution which seems to work, but I'm not as happy as I'd like with it. I'm about to try doing the SetForgroundWindow() in in App A to get it to bring App B to the foreground and my understanding is this should work. Up untill now I was trying to get App B to bring itself to the foreground.
This is the start of a new day for me (here in Oz) which I hope will be better than yesterday.
Neville Franks, Author of ED for Windows www.getsoft.com and coming soon: Surfulater www.surfulater.com
|
|
|
|
|
It works fine for me in and out of the debugger as a way for an application to bring itself to the foreground. I simply have StealFocus(this) in a dialog that shows a vital message.
The opinions expressed in this communication do not necessarily represent those of the author (especially if you find them impolite, discourteous or inflammatory).
|
|
|
|
|
Phil J Pearson wrote:
It works fine for me in and out of the debugger as a way for an application to bring itself to the foreground. I simply have StealFocus(this) in a dialog that shows a vital message.
What version of Windows are you using? Does this bring the app to the foreground or just the dialog? I assume both as one will follow the other but need to ask.
I'm using XP with SP1. I'm also using a P3 550Mhz box which tends to show problems that newer, faster machines don't.
Neville Franks, Author of ED for Windows www.getsoft.com and coming soon: Surfulater www.surfulater.com
|
|
|
|
|
It works on Windows 2000, XP, XP SP1a and XP SP2 on a range of hardware from Celeron 300 onwards.
It brings the whole app to the foreground.
The opinions expressed in this communication do not necessarily represent those of the author (especially if you find them impolite, discourteous or inflammatory).
|
|
|
|
|
I need to modify the style of a window owned by another application under Windows 98/ME and XP/2000. I can get it to work under XP, but not 98.
Windows XP
In XP (and hopefully 2000) the following code works:
DWORD dwStyle, dwError;
if (dwStyle = GetWindowLongPtr (hWnd, GWL_STYLE))
{
dwStyle &= ~(WS_TILEDWINDOW | WS_CHILD | WS_POPUP);
dwStyle |= WS_BORDER | WS_OVERLAPPED;
SetLastError (0);
if (0 == SetWindowLongPtr (hWnd, GWL_STYLE, dwStyle) && 0 != (dwError = GetLastError ()))
{
CString csMess;
csMess.Format ("SetWindowLongPtr Failed: %lX", dwError);
AfxMessageBox (csMess, MB_ICONSTOP);
}
}
To make this work in XP I first have to set some privileges as below:
bool CTools::SetPrivileges ()
{
bool bRet = false;
HANDLE hToken;
if (OpenProcessToken (GetCurrentProcess (), TOKEN_ADJUST_PRIVILEGES, &hToken))
{
TOKEN_PRIVILEGES tPriv;
tPriv.PrivilegeCount = 1;
if (LookupPrivilegeValue ("", SE_DEBUG_NAME, &tPriv.Privileges[0].Luid))
{
tPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
if (AdjustTokenPrivileges (hToken, FALSE, &tPriv, NULL, NULL, NULL) &&
GetLastError() == ERROR_SUCCESS)
bRet = true;
}
CloseHandle (hToken);
}
return bRet;
}
Windows 98
Under Windows 98 these don't work. SetWindowLongPtr returns 0 (usually non-zero when it works) but GetLastError returns 0 too. More importantly, the style doesn't change. GetWindowLongPtr does work though. There may be a permissions problem in 98 like there was in XP but SetPrivileges is not relevant to 98.
Documentation does say:
"Windows 95/98/Me: The SetWindowLong function may fail if the window specified by the hWnd parameter does not belong to the same process as the calling thread."
I also tried this, without success in 98 or XP (even with priveleges set):
CWnd::ModifyStyle (hWnd, WS_TILEDWINDOW | WS_CHILD | WS_POPUP, WS_BORDER | WS_OVERLAPPED, 0);
In XP it indicates failure with it's return value. In 98 it pretends to work but the style doesn't change. Does anyone know another way to change a windows style?
I don't know what to do to set the style of a window my application doesn't own under Win 98. Any ideas? Thanks in advance!
Alex Gibbs
|
|
|
|
|
I don't know which version of MFC you're using, but CWnd::ModifyStyle doesn't have a parameter for window handles. According to Microsoft documentation (msdn.microsoft.com/library/default.asp), the function is defined as:
BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0);
So you don't need a window handle, just a CWnd pointer to the application in question (I don't know how to do that myself, but I'm sure other forum members can help) .
|
|
|
|
|
I too saw that only the one you mentioned is documented. I found the other when Dev Studio showed two forms to choose from when I was typing it in. Going to the declaration takes you to afxwin.h in the CWnd declaration:
static BOOL PASCAL ModifyStyle(HWND hWnd, DWORD dwRemove, DWORD dwAdd, UINT nFlags);
which of course also has:
BOOL ModifyStyle(DWORD dwRemove, DWORD dwAdd, UINT nFlags = 0);
I tried both forms under 98 and neither worked. Both now work in XP though. At least it was another thing to try.
Alex Gibbs
|
|
|
|
|
Here is an update. I can modify another window's style under XP using any of the calls below, if the priveleges are set as mentioned in the first post:
<br />
SetWindowLongPtr (hWnd, GWL_STYLE, dwStyle);<br />
CWnd::ModifyStyle (hWnd, dwRemove, dwAdd, 0);<br />
pCWnd->ModifyStyle (dwRemove, dwAdd);<br />
However, none of them change the visible appearance of a window under 98. Remember I am trying to change the window of another process. I think the problem is one of priveleges/permissions in 98.
I found something else that might be relevant at MSDN, but I don't think it is the problem. MSDN Article, 5th paragraph: "Windows 95/98/Me automatically adds and removes the WS_EX_WINDOWEDGE style for windows in all applications. ..."
Anyone able to help with priveleges/permissions in 98?
Alex Gibbs
|
|
|
|
|
It's possible that the window of another process "undos" any changes made to it. I know of some programmers who put code in their MFC applications to prevent certain window style changes. I believe the Windows Media Player exhibits this behaviour.
If this other process is of your own creation, then you may want to use user-defined messages to invoke certain behaviour.
|
|
|
|