|
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.
|
|
|
|
|
Hello all. I need some help regarding add-ins.
I want to create an Add-in for the Visual Basic Editor (open any Office application and hit Alt+F11 to see what I'm talking about). I also want to make it using Visual C++ since that's what I'm familiar with.
I don't have any experience with ATL/COM (yet), so if anyone out there can provide some information I would be very greatful. A step-by-step guide would also be helpful. At the very least, some links/code snippets to get me started.
Thank you.
|
|
|
|
|
I think that's a great idea also. Most of my co-workers use VB6 and they wish they had a way to use macros like in .Net or VC6.
[insert witty comment here]
bdiamond
|
|
|
|
|
I have found an example that uses C++/ATL to make a COM add-in for Office, but I'm new to ATL/COM and am having difficulties understanding it. If you do a search on msdn.microsoft.com for "comaddin.exe" you'll find it.
|
|
|
|
|
I've finaly figured out how to get the window shape for a visual style.
By going through the GetThemeBackgroundRegion, I can retrieve a handle to a HRGN class. Then I use GetRegionData from the class to retrive the structure mentioned above, which should give me a collection of rectangles. However, i'm mildly confused.
This is the content of the MSDN:
The RGNDATA structure contains a header and an array of rectangles that compose a region. These rectangles, sorted top to bottom left to right, do not overlap.
typedef struct _RGNDATA { /* rgnd */
RGNDATAHEADER rdh;
char Buffer[1];
} RGNDATA;
Parameters
rdh:
Specifies a RGNDATAHEADER structure. (For more information on this structure, see the Platform SDK.) The members of this structure specify the type of region (whether it is rectangular or trapezoidal), the number of rectangles that make up the region, the size of the buffer that contains the rectangle structures, and so on.
Buffer:
Specifies an arbitrary-size buffer that contains the RECT structures that make up the region.
Now... the confusing part is. Where is the array of RECT? It's a single element array of Char.... Is there some special approach to this, or is it a typo / mistake? And what does "arbitary size buffer" mean? I know it's a retrieved value, but I need to marshal it in C#, so kind of need the additional information.
Cheers guys.
Cata
|
|
|
|
|
I have a small utility app that I'm making using ReadDirectoryChangesW() (thanks to DavidCrow). Here's the function:
UINT WatchFolder( LPVOID pDlg )
{
try
{
USES_CONVERSION;
CBRFolderWatcherDlg* pd = (CBRFolderWatcherDlg*) pDlg;
HANDLE hDir = CreateFile( gstrPath,FILE_LIST_DIRECTORY, FILE_SHARE_READ|FILE_SHARE_DELETE, NULL,
OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,NULL );
FILE_NOTIFY_INFORMATION Buffer[1024];
DWORD BytesReturned;
while( ReadDirectoryChangesW(hDir,&Buffer,sizeof(Buffer),TRUE,
FILE_NOTIFY_CHANGE_CREATION|FILE_NOTIFY_CHANGE_LAST_ACCESS|FILE_NOTIFY_CHANGE_LAST_WRITE|
FILE_NOTIFY_CHANGE_SIZE|FILE_NOTIFY_CHANGE_ATTRIBUTES|FILE_NOTIFY_CHANGE_DIR_NAME|FILE_NOTIFY_CHANGE_FILE_NAME,
&BytesReturned, NULL, NULL) )
{
CTime tm = CTime::GetCurrentTime();
switch(Buffer[0].Action)
{
case FILE_ACTION_ADDED:
int i=0;
do
{
CString strTime;
CTime tm = CTime::GetCurrentTime();
strTime = tm.Format("%m/%d/%Y %I:%M %p");
CString buf = CString(Buffer[i].FileName).Left(Buffer[i].FileNameLength / 2) ;
int nRow = pd->m_lvw.GetItemCount();
nRow = pd->m_lvw.InsertItem(nRow,buf);
pd->m_lvw.SetItemText(nRow,1,strTime);
i++;
}while (!Buffer[i].NextEntryOffset);
break;
}
}
}
MYCATCHALL
return 0;
}
I call this function using AfxBeginThread(). It works, but right now the only way for the thread to stop executing is to end the app. I thought to make a global variable that I could set if I clicked a 'Cancel' button, but that doesn't work because ReadDirectoryChangesW() doesn't finish executing until it receives a notification, at which time it continues through the loop. I'm trying to find if there's a way I can do something like this:
<br />
m_pThread = AfxBeginThread(WatchFolder,this);<br />
<br />
EndThread(m_pThread);
Any help is appreciated. Thanks in advance
[insert witty comment here]
bdiamond
|
|
|
|
|
I would suggest reworking the directory watching code to use an overlapped scheme. Then youc na wait on 2 events - one for the overlapped IO to be ready, and another signaled by your program to exit the thread.
If your overlapped event is set, then get the overlapped result and process the data.
If the thread exit event is set, then cancel the overlapped request and leave your thread normally.
|
|
|
|
|
I've now created my thread suspended, then start it with a call to m_pThread->ResumeThread() . Then when the user clicks 'Cancel' I call SuspendThread() and then delete() on the CWinThread object. It works (meaning that files no longer show up), and I don't get any type of errors in my debug window when I terminate the app. So is this okay?
[insert witty comment here]
bdiamond
|
|
|
|
|
It is not ideal, but it is probably okay because windows is cleaning up your program's leaked handles and other memory leaks.
You might want to watch task manager and make sure you are not leaking some global GDI or other kernel objects.
Do this oepration on your program about 100 times and watch the handles available in task manager un der the 'performance' tab. The number of handles should not constantly increase, otherwise, your program is leaking a global handle in the kernel space that will eventually lead to windows shutting down.
The BEST thing is to always exit cleanly, and this recent solution of yours is not clean, unless you are able to successfully close the directory watch handles, even though your thread might be in the middle of waiting. Just because it is suspended, does not mean it was not in the middle of waiting.
|
|
|
|
|
I tried what you said, using my 'Start' and 'Stop'(cancel) buttons. Watching Task Manager, the number of handles is steadily increasing, as well as the number of threads. I don't think this will be a very big deal for my app because I have an option that will allow the app to start the thread automatically in OnInitDialog(). The app will only ever be watching one folder and we will probably put it in the StartUp folder so that everytime the server restarts, the app will start up also.
However, I would still like to do it a better way. I kinda looked at your first response, and I'm sorta clueless as to what you're talking about (I still consider myself a C++ beginner). But I DO know that putting a band-aid on a gunshot wound will lead to bigger problems. So if you have the time to elaborate further on your earlier comment, I'd appreciate it. The first way I had it was that the user had to actually close the app for it to stop watching the folder...I'm wondering if I should've just left it like that?
Thanks for your help!!
[insert witty comment here]
bdiamond
|
|
|
|
|
I apologize for not being clear
Watch the task manager handle count AFTER your program has closed.
I expected that you would see the count going up steadily while starting and stopping your thread, since you are killing a thread in progress.
This is what I would check, given the way it works now:
1. Start task amanger and write down the number of handles in use.
2. Start your progrma and start and stop your thread several times. You already indicated the handle count increases.
3. Close the program, and wait a moment, and then see if the handle count has returned to nearly the original number.
4. Do steps 1 - 3 about 20 times. IF the handle count returns and stays at about the original number, before starting any tests, then you are problably not in danger of stopping Windows because of handle leaks.
I will take it into consideration to post some aritcle in the future for a 'thread safe file change watcher'
|
|
|
|
|
yes, it returns to roughly the same number, give or take a few. So I guess it's cool. thanks!!!
[insert witty comment here]
bdiamond
|
|
|
|
|
|
Hi all,
I'm having a problem with my CSplitterWnd SDI app ...
It's split into 2 frames, with a CEditView on the left side, and a CDialog panel on the right with some button controls on it. After I click a button on the right panel, then do a menu->file->print, I catch a ID_FILE_PRINT message in CMainFrame. I'd like to send this to my view.
Here's my code to do this:
<br />
MainFrm.cpp -- OnFilePrint(....)<br />
<br />
CMYEDITView *pView = (CMYEDITView *)m_wndSplitter.GetPane(0,0);<br />
pView->SendMessage(ID_FILE_PRINT_PREVIEW);<br />
The message is never received by the CEditView's message map.
My question is this: Do I need to do anything special to set focus to this view before sending the Message? or is something else wrong here?
Thanks a million,
Mike
"I bet Einstein turned himself all sorts of colors before he invented the light bulb." -- Homer J.
|
|
|
|
|
Hi
Check the view's address .if prb with address get the splitters' address using getparent frame
Hope this will help
Sujan
|
|
|
|
|
Is it possible to write a shell handler that gets called when you double click a folder and that would allow you to put your own processing in place? So you could look at the directory name, and if it (the directory name) ended in "*.app" you would execute the executable that was inside of it, as opposed to opening the directory in explorer. Is this even possible ?
Thanks
Jim
¡El diablo está en mis pantalones! ¡Mire, mire!
Real Mentats use only 100% pure, unfooled around with Sapho Juice(tm)!
SELECT * FROM User WHERE Clue > 0
0 rows returned
|
|
|
|
|
Michael Dunn has written seven articles on Shell programming. Here is a link to the first one. Hopefully one of them will steer you in the right direction.
"When I was born I was so surprised that I didn't talk for a year and a half." - Gracie Allen
|
|
|
|
|
Hi,
How can I change the menu item properties dynamically? basically, I want to have the menu caption "Running!" when a certain code in my application is running and "Stopped" when the code is in standby.
Thank you for your help
Zakaria
|
|
|
|
|
Add a handler for the update of the menu item eg:
void CDocClass::OnUpdateMenuItemName(CCmdUI* pCmdUI)
{
if (m_bRunning)
pCmdUI->SetText(_T("Running"));
else
pCmdUI->SetText(_T("Stopped"));
}
Ant.
I'm hard, yet soft. I'm coloured, yet clear. I'm fruity and sweet. I'm jelly, what am I? Muse on it further, I shall return! - David Williams (Little Britain)
|
|
|
|
|
I have a memory leak and think I have found it. So my question is whats the best way to terminate this thread.
The final tidy-up section of code is never reached.
The thread reads UDP data packets and updates a database; but on my main program exit routine should I kill this thread? As could be waiting on a read.
while(g_bUDP_Socket_Created)<br />
{<br />
int len = sizeof(RxBuffer);<br />
bytesRead = recvfrom (conn_socket, (char *)&RxBuffer, sizeof(Data), 0, (struct sockaddr *)&from, &length);<br />
if (bytesRead == SOCKET_ERROR) <br />
{<br />
g_sFormatting.Format("recvfrom() failed: %d\n",WSAGetLastError());<br />
AfxMessageBox(g_sFormatting);<br />
WSACleanup();<br />
return -1;<br />
}<br />
::EnterCriticalSection(&g_csRxLock);
memcpy(&g_RxData, &RxBuffer, sizeof(Data));<br />
UpdateDataBase();<br />
::LeaveCriticalSection(&g_csRxLock);
g_nUDPCounter++;<br />
}<br />
closesocket(conn_socket);<br />
WSACleanup();<br />
return 0;
|
|
|
|
|
Seems to me you should be using an asynchronous 'unblocked' socket. Your thread should wait on an exit event and a socket event (2 events) with WaitForMultipleObejct, and only issue the socket read if socket data is ready. Otherwisee you WILL just sit there until data arrives.
See WSAEventSelect:
"As in the case of the select and WSAAsyncSelect functions, WSAEventSelect will frequently be used to determine when a data transfer operation (send or recv) can be issued with the expectation of immediate success. Nevertheless, a robust application must be prepared for the possibility that the event object is set and it issues a Windows Sockets call that returns WSAEWOULDBLOCK immediately. For example, the following sequence of operations is possible:"
Then, your application main thread can set the event for the thread to exit, and it should not be otherwise 'blocked' waiting for data reception on the socket.
|
|
|
|
|