|
Yes, that's how I'm capturing the STN_CLICKED event.
|
|
|
|
|
All,
I posted this message on the following board, but since this area gets more traffic, and also since I don't believe the problem is necessarily related to the serial code, I will repost it here:
http://www.codeproject.com/system/serial.asp?target=serial
Ramon,
I'm guessing that you might be the only one that might be able to answer this. I have had great success incorporating your sample code into my project. I am controlling an external device that I write to once a second to start it performing a series of A/D conversions. When it is done it sends the data back, and the reader thread notifies my dialog box that there is data via the PostMessage routine. So far so good.
Because I had a need to send data to the external device every second, I created a second writer thread, similar to the reader thread. I essentially copied the code and changed names and such and I now bring up both threads. My main dialog window is still the destination for the messages that get sent by the PostMessage routine.
Here is my problem. The application that I incorporated your code into has a hard coded loop in the main DialogProc routine. This is perhaps not good programming practice as it hangs the code from processing any windows messages, including the messages from PostMessage that indicate that there is serial data to be read. What happens is then that I miss the serial data. What I need to be able to do is run that main loop AND process the messages that indicate there is serial data coming in.
I tried to solve this by creating a new window within the writer thread that has it's own doalog processor for windows messages. Here is that code:
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = (WNDPROC) MyWindowProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInstance;
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wc.lpszMenuName = NULL;
wc.lpszClassName = "MyWindowClass";
returned_class_atom = RegisterClass(&wc);
if (!returned_class_atom)
{
last_err = GetLastError();
}
agilent_receiver = CreateWindow("MyWindowClass",
"Nothing",
WS_MAXIMIZE,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
CW_USEDEFAULT,
HWND_MESSAGE,
NULL,
NULL,
lpvoid_null);
if (agilent_receiver == NULL)
{
debug_stop = 1;
last_err = GetLastError();
}
This code all runs fine, and when I run it in debug the call to CreateWindow results in a series of 7 messages being sent to the message processing routine MyWindowProc which is the routine specified in the call to RegisterClass when the newly created class is registered. The window handle agilent_receiver comes back with a good value.
I then thought that I could simply reroute the notifications by changing the CSerialWnd::OnEvent routine as follows:
void CSerialWnd::OnEvent (EEvent eEvent, EError eError)
{
int a,b;
if (PostMessage(agilent_receiver,m_nComMsg,MAKEWPARAM(eEvent,eError),LPARAM(m_lParam)))
a=b;
else
b=a;
}
The funny thing here is that when I put in agilent_receiver as the destination instead of your value of m_hwndDest, I don't receive the notifications in my message handler. The PostMessage call appears to work as it returns a non-zero value.
I don't think it has anything to do with the threads, because your code sends the windows messages from the reader thread to the main GUI window message handler, which is in a different thread. I am just trying to send those same windows messages to a new window created in the writer thread.
Any ideas,
Robert
|
|
|
|
|
I am not fully sure what you are trying to achieve but when posting messages between threads you really should use PostThreadMessage()
PostThreadMessage posts messages to the queue of the specified thread without waiting.
Ant.
|
|
|
|
|
Antony,
Thanks for the tip. I switched the call to PostThreadMessage and in my thread I now periodically check for message arrival with PeekMessage and am seeing them there.
Robert
|
|
|
|
|
If you have a hard coded lopp in your UI thread that stops it processing messages, you can add this code to the loop to allow other messages to be processed:
MSG msg;
while (::PeekMessage(&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE))
{
::TranslateMessage(&msg);
::DispatchMessage(&msg);
}
Be careful as the cancel/ok buttons and the original button that set you loop going etc will be able to be used by the user. You need to set the dialog up in such cases that all commands you don;t want to be run during this long process are disabled.
Roger Allen - Sonork 100.10016
Strong Sad:
Clever I am? Next to no one.
Undiscovered and soggy.
Look up. Look down. They're around.
Probably laughing. Still, bright, watery.
Listed among the top. Ten.
Nine. Late night. Early morn.
Early mourn. Now I sleep.
|
|
|
|
|
Hi,
i am looking for some api, or method
to check the current status of a service
and return a value to a program,
then if needs be i can start the service
via net start or relevant method
Thanks
|
|
|
|
|
I am not sure about your specific problem, but you may try using something like this to find your service:
<br />
SC_HANDLE hM = OpenSCManager(NULL,NULL,SC_MANAGER_ENUMERATE_SERVICE);<br />
if (hM)<br />
{<br />
ENUM_SERVICE_STATUS stat[1024];<br />
DWORD dwNeeded;<br />
DWORD dwRet;<br />
DWORD dwFirst = 0;<br />
if (EnumServicesStatus(hM,SERVICE_WIN32|SERVICE_DRIVER,SERVICE_STATE_ALL,stat,sizeof(stat),&dwNeeded,&dwRet,&dwFirst))<br />
{<br />
for (DWORD n=0;n<dwRet;n++)<br />
{<br />
char sz[256];<br />
sprintf(sz,"%s,%s,%i\n",stat[n].lpDisplayName,stat[n].lpServiceName,stat[n].ServiceStatus.dwCurrentState);<br />
OutputDebugString(sz);<br />
}<br />
}<br />
CloseServiceHandle(hM);<br />
}<br />
Or, if you are already in posession of the service handle,
<br />
BOOL QueryServiceStatus(<br />
SC_HANDLE hService,
LPSERVICE_STATUS lpServiceStatus
);<br />
Enjoy!
Maksim Lepikhin
www.softforpros.com
|
|
|
|
|
BOOL QueryServiceStatus(
SC_HANDLE hService,
LPSERVICE_STATUS lpServiceStatus
);
get its detailed information from MSDN!
|
|
|
|
|
I have a simple server that seems to be leaking handles.
The handle is to a registry key :
HKLM\SYSTEM\ControlSet001\Services\DnsCache\Parameters
In particular 1 handle (key) to this is leaked for each client connection.
The service is simple, it calls socket(AF_INET, SOCK_STREAM, IPPROTO_TCP), bind(), listen() then waits in a loop on accept().
Each accept() creates a thread that handles the connection.
All the thread does is some predefined sync send() and recv() calls then exits.
Everything is being closed correctly, thread, socket, ...
But each closed connection leaves another one of these handles around.
The handles don't appear to be cached, as i have tried leaving the service running with no conncetions for hours to see if they get 'cleaned up' - no joy.
Short of disabling the DNS Client service, does anyone have any ideas ?
[EDIT]
The handle is being created by SQLConnectA().
[/EDIT]
[EDIT_2]
I'm able to get rid of the leak by enabling connection pooling via :
::SQLSetEnvAttr(NULL, SQL_ATTR_CONNECTION_POOLING, (void*)SQL_CP_ONE_PER_DRIVER, 0);
[/EDIT_2]
...cmk
Save the whales - collect the whole set
|
|
|
|
|
Is it possible to read binary data from a music or karaoke CD using the standard I/O functions in Win32? My purpose is to examine the data structure and learn more about them, possibly to try writing my own programs for managing content. Is this likely to require, instead, something at the device driver level?
Will Build Nuclear Missile For Food - No Target Too Small
|
|
|
|
|
Can't really answer your questions, but here's a pretty good FAQ that gives an overview, as well as links to more in-depth information:
http://www.cdrfaq.org/faq02.html#S2-43[^]
How do you move in a world of fog, That's always changing things?
Makes me wish that i could be a dog, When i see the price that you pay.
|
|
|
|
|
Excellent link, Josh - Thanks!
It looks like, if I'm going to pursue this, I'll need to install the DDK and learn to use it. Oh well, nothing easy is worth having...
Will Build Nuclear Missile For Food - No Target Too Small
|
|
|
|
|
What OS do you want compatiblity with? You can use SPTI in NT and use ASPI in 9x
SPTI
Have a look for opening CDRom drives using CreateFile, you can read sectors other than data using DeviceIoControl and IOCTL_CDROM_RAW_READ
ASPI
If you using ASPI then you can use many of the read commands defined in the SCSI 3 specification. READ_CD being your best bet.
Regards,
Ceri
|
|
|
|
|
Sounds promising - thanks!
Will Build Nuclear Missile For Food - No Target Too Small
|
|
|
|
|
I'm writing an app that when a certain event is received it brings itself forward to the top window on the z-order. However I cannot get this to happen on a win xp pro environment.
I tried this example that I found but this does not work
AttachThreadInput(<br />
GetWindowThreadProcessId(<br />
::GetForegroundWindow(),NULL),<br />
GetCurrentThreadId(),TRUE);<br />
<br />
SetForegroundWindow();<br />
SetFocus();
<br />
AttachThreadInput(<br />
GetWindowThreadProcessId(<br />
::GetForegroundWindow(),NULL),<br />
GetCurrentThreadId(),FALSE);
I've also tried this:
<br />
::AttachThreadInput(GetWindowThreadProcessId(hWnd, NULL) ,GetCurrentThreadId(), TRUE);<br />
::DefWindowProc(hWnd, WM_SYSCOMMAND, SC_RESTORE, NULL);<br />
::SetForegroundWindow(hWnd);<br />
::SetFocus(hWnd);<br />
::ShowWindow(hWnd, SW_SHOWNORMAL);<br />
::AttachThreadInput(GetWindowThreadProcessId(hWnd, NULL) ,GetCurrentThreadId(), FALSE);<br />
Still does not being itself forward.
Does anyone have any suggestions?
Thanks
Tom Wright
tawright915@yahoo.com
|
|
|
|
|
You could try setting it as the topmost window
::SetWindowPos(hWnd, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE);
Though you will have to revoke this if you want other windows to move over it afterwards.
Ant.
|
|
|
|
|
OR replace HWND_TOPMOST with HWDTOP to move to the top without making it permanent.
Christian
I have drunk the cool-aid and found it wan and bitter. - Chris Maunder
|
|
|
|
|
So, you're actually trying to call SetForegroundWindow , but the lock feature is working.
Good. It's supposed to. The user doesn't want to be interrupted by your program. If you really must, it is possible to change the lockout behaviour using SystemParametersInfo(SPI_SETFOREGROUNDLOCKTIMEOUT) , but you can only do this if you're already the foreground window or a call to SetForegroundWindow would succeed.
Stability. What an interesting concept. -- Chris Maunder
|
|
|
|
|
I do not believe that this is the case. This is why. Currently I'm writing this code in a dll that a COBOL application is calling (so that it can pop itself to the top of the z-order). This same code is in a test .exe and it works great. I type in the title of the window I want to come forward and it comes forward.
This same code works great on Winnt 4.0, w2k, but I cannot get it to work on XP. So what is the difference between 2000 and XP?
Thanks for the help
Tom Wright
tawright915@yahoo.com
|
|
|
|
|
I have been using an application-defined comparison function for sorting CListCtrl in Report format. The item string is obtained by searching the list for a match on the item data (see below). This works fine if there are subitems, however with NO subitems the ASSERT fires. If the list control is redrawn during the sort, the row with lParam1 is missing - replaced by a duplicate of another row.
Any ideas?
Many thanks.
int CALLBACK CSortListCtl::CompareItems( LPARAM lParam1, LPARAM lParam2, LPARAM lParamData )<br />
{<br />
....<br />
<br />
LVFINDINFO findInfo;<br />
findInfo.flags = LVFI_PARAM;<br />
findInfo.lParam = lParam1;<br />
int index1 = pListCtrl->FindItem( &findInfo );<br />
ASSERT( index1 > -1 );<br />
CString text1 = pListCtrl->GetItemText( index1, subItem );<br />
<br />
....<br />
}
|
|
|
|
|
This is the incorrect usage of the comparison function. When you add items to a list control using InsertItem() , you should follow that with a call to SetItemData() . Then in the comparison function, the values passed in as lParam1 and lParam2 are used as pointers to the item data. Here's a brief example:
CString *pName = new CString("Mason");
int nItem = m_listctrl.InsertItem(0, *pName);
pName = new CString("Dixon");
nItem = m_listctrl.InsertItem(1, *pName);
pName = new CString("Woodrow");
nItem = m_listctrl.InsertItem(2, *pName);
...
int CompareFunc( LPARAM lParam1, LPARAM lParam2, LPARAM lParamData )
{
CString *str1 = (CString *) lParam1,
*str2 = (CString *) lParam2;
return str1->CompareNoCase(*str2);
}
"The pointy end goes in the other man." - Antonio Banderas (Zorro, 1998)
|
|
|
|
|
If you use the sequence
pName = new CString("Dixon");<br />
nItem = m_listctrl.InsertItem(1, *pName);<br />
m_listctrl.SetItemData(1, pName);
repetitively, all the string data in the list is duplicated in the CString objects. You will also need to add extra code to delete all the CStrings before the control is destroyed (or possibly subclass and override OnDestroy() ). Hence the attraction of using FindItem() albeit at the cost of lots of searches.
The point that I wanted to make is that FindItem() doesn't appear to work during sorting if you have no subitems - unless I've got my code wrong.
Of course, we would not be having this discussion if instead of supplying lParam's, LVITEM's were passed instead with a predefined mask.
|
|
|
|
|
Background:
My application restricts the capabilities of users without administrator privileges and provides an "administrator override" capability that allows an administrator to supply credentials so that restricted operations may be performed without terminating the app. This capability is designed to work on Windows 2000 and XP. The app requests user credentials with a logon dialog box. It then validates them and impersonates the user with administrator privileges using code modified from the samples supplied with Microsoft KB article Q180548. This mechanism works correctly on Windows 2000 SP3.
Problem:
After installing SP4 or some other recent Hotfix, the administrator override capability no longer works. After the app impersonates a user with administrator privileges, it can no longer open a registry key in HKEY_CURRENT_USER for reading and writing. The call:
RegOpenKeyEx (HKEY_CURRENT_USER, pszKeyName, 0,
KEY_READ|KEY_WRITE, &hRegKey);
fails, returning a value of 1346 (0x542), listed in Winerror.h as ERROR_BAD_IMPERSONATION_LEVEL.
What must I change in the app to fix this problem?
|
|
|
|
|
ICantChangeMyAcct wrote:
After the app impersonates a user with administrator privileges...
Are you sure this part still works? The 0x542 error has two meanings: either a required impersonation level was not provided, or the provided impersonation level is invalid.
"The pointy end goes in the other man." - Antonio Banderas (Zorro, 1998)
|
|
|
|
|
I'm not sure what "works" means. The Q180548 code uses secur32.dll functions to generate a "client context" and a "server context", then calls the function ImpersonateSecurityContext() with the *server's* context handle (!?!) This function returns SEC_E_OK, indicating that the impersonation "worked". My app doesn't use the context handle in system calls or do anything that requires administrator privileges.
|
|
|
|
|