|
Just be careful of the potential headaches caused by VS2005's manifest generation. Apps built by VS2005 require the presence of an embedded or external manifest when run on XP and Vista. I've suffered (and continue to suffer) no end of pain trying to get my app to run on other people's XP boxes, thanks to VS2005's inconsistent generation of manifests.
I've had no such problem with VC6 built versions of the same app.
/ravi
|
|
|
|
|
There's no simple answer. If VC6 is meeting your current needs, why switch? I for one don't think the VC8 IDE is better.
|
|
|
|
|
If you're writing VC++ code, VS2005 makes your life harder because the new IDE is built around .Net development.
For VC++ programmers, the ONLY real reason to switch is to get the newest version of MFC, but be prepared for a bit of work to get your code to compile clean. A lot of MFC functionality has changed (be especially aware of COleDateTime changes). Also, if you do move to VS2005, make sure you also download and install the service pack that was released in December.
We had an app that was over 670,000 lines of code spread across 24 sub-projects. The initial compile resulted in over 2000 errors, and over 4000 warnings. It only took about two hours re-factor the code code because a lot of the warnings/errors were just duplicates of prior entries.
Lastly, despite what Christian said, VC6 is most certainly NOT rubbish. If you're in the middle of development on a project using VC6, I'd stick with VC6 for that version and move to VS2005 for the next major revision.
"Why don't you tie a kerosene-soaked rag around your ankles so the ants won't climb up and eat your candy ass..." - Dale Earnhardt, 1997 ----- "...the staggering layers of obscenity in your statement make it a work of art on so many levels." - Jason Jystad, 10/26/2001
|
|
|
|
|
Thanks for all the input. It's very helpful.
When do you think that Visual C++ 6 will be out-of-date? i.e, Microsoft may decide one day to stop supporting it and it may have trouble with compatability with the next version of windows.
|
|
|
|
|
I am using Visual C++ 6.0 with MFC. I have an application that spawns a user interface thread that is a 'CProgress' dialog box with a progress control and a 'Cancel Thread' button. There are a couple of things happening depending where I put the declaration of the CProgress.
BOOL UIThread::InitInstance()
{
m_pMainWnd = new CProgress;
m_pMainWnd->SetForegroundWindow();
m_pMainWnd->CenterWindow(NULL);
m_pMainWnd->ShowWindow(SW_SHOW);
CoInitialize();
return TRUE;
}
int UIThread::Run()
{
CMyDialog dlgMyDialog;
dlgMyDialog.DoModal();
return CWinThread::Run();
}
If the CProgress dialog box is declared in InitInstance() as shown above the call to dlgMyDialog.DoModal() doesn't cause any problems but the CProgress dialog box is displayed without any of the buttons or controls and it does not have focus. I can fix this problem by putting the declaration of CProgress into the UIThread constructor but then the call to dlgMyDialog.DoModal() crashes the app (specifically at file wincore.cpp line 895). Now if I keep the declaration of CProgress in InitInstance() to keep the app from crashing, the CProgress dialog box is not fully drawn until CWinThread::Run() is executed. Can anyone help me with the commands needed to make the CProgress dialog box fully functional so I can cancel the thread with the click of a button?
Thanks
Buck
|
|
|
|
|
It doesn't look like your UIThread thread processes any messages so that won't work.
I think it would be much much easier to use a modeless dialog.
|
|
|
|
|
The point is that the class wizard creates the code when adding a class with a base class of CWinThread() and that the code the thread executes should be in the UIThread::Run() function. If my thread execution is not performed by Run() then where do I put my thread code? This really shouldn't be this difficult. All I want is to click a button to start the test and click another button to abort the test.
|
|
|
|
|
Right. Kind of a catch-22 deal - you can't create a window without running the threads message
loop and you can't run the message loop before creating the window
If you insist on a separate thread for just the modal dialog then start the UI thread - run it,
and post a thread message to it. Respond to the thread message and then call DoModal() on the
dialog.
That's still way more complicated than it needs to be.
|
|
|
|
|
Very much a catch 22. Let me say that I am NOT a Windows programmer. How would you set it up? My tab page has a button that invokes OnButtonBeginTest() that executes the test code (that could take an hour). While the test is running I can't click on any other buttons on my tab page. If I could then I would add an abort test button to the tab page.
|
|
|
|
|
BuckBrown wrote: Let me say that I am NOT a Windows programmer
Too late - you're a windows programmer.
I prefer 1 UI thread (the CWinApp one in MFC).
So, I would
1) respond to the button click
2) create/show a modeless progress dialog
3) disable the main window if appropriate or at least the button so the user can't click it again
4) start a worker thread which executes the test code
4a)The worker thread could periodically post messages to the modeless dialog to indicate progress
(if that info is available) - this could be done via class method as well but then you may have
to handle thread synchronization.
5) If the user clicks cancel (if provided in the modeless dialog) then somehow inform the thread
to terminate - using a flag variable or event object.
6) If the test thread ends normally then it could post a message to the main window or the dialog
(whichever is appropriate) indicating completion.
7) on receipt of the completion message, destroy/cleanup the thread object, the modeless dialog,
and reanable any disabled windows from step 3
Something like that.
Mark
|
|
|
|
|
Thanks, I'll try this approach tomorrow. Something's gotta give. I've been trying to do this since Monday morning - 32 hours to not yet do what an experienced Windows guy could do in 32 minutes!
|
|
|
|
|
Also, the following code (where I was spawing the UI thread) greys out the area on my tab page where the modeless dialog should appear but the modeless box does not appear until the AfxMessageBox() command.
pInProgress->Create(IDD_DIALOG_PROGRESS, this);
pInProgress->CenterWindow();
pInProgress->SetForegroundWindow();
pInProgress->UpdateData(TRUE);
pInProgress->UpdateWindow();
pInProgress->ShowWindow(SW_SHOW);
Sleep(5000);
AfxMessageBox("Wait");
// theApp.m_pThread = AfxBeginThread(RUNTIME_CLASS(UIThread), 0, THREAD_PRIORITY_NORMAL);
Isn't there a way to flush the messages? Or at least FORCE this window to display?
Everthing I do in Windows needs some information that I dont have access to!
|
|
|
|
|
The messages won't flush until the thread flushing the messages runs
The Sleep() is preventing that.
|
|
|
|
|
What happens if you move the "pInProgress->UpdateWindow();" below the ShowWindow() call?
|
|
|
|
|
|
If you can break up the work done in the spawned thread into separate subtasks, you could use this[^] progress dialog class.
/ravi
|
|
|
|
|
I need to discover the presence of a Bluetooth device (and communicate with it via a virtual serial port). Device discover is an easy task using Microsoft's Bluetooth API - it works very well indeed!
However, Microsoft's API does not appear to be compatible with a large number of bluetooth adaptors out there (primarily Widcomm, but also BlueSolei, Toshiba, etc). So on these adaptors, my application is likely to bomb I understand this is also a problem pre XP SP2.
So, does any one know of an SDK (for C++ use) which provides a simple universal unified API (or wrapper) for the various Bluetooth implementations out there (or at least the main two)?
You would have thought the developers of Bluetooth could have sat at a table and agreed some basic common API for the software side of things like they did with the hardware side, but apparently not!
Much appreciated
--
The Obliterator
|
|
|
|
|
Obliterator wrote: You would have thought the developers of Bluetooth could have sat at a table and agreed some basic common API for the software side of things like they did with the hardware side, but apparently not!
Bluetooth 'developpers' as you call them didn't work at all on a hardware part. They only developped a specification that defines how different devices can communicate together, the different layers of the BT stack, the different profiles, ... The software API that you are looking for is way outside the scope of the Bluetooth specifications (a lot of devices won't even need to be 'managed' by a operating system).
I never worked with the Microsoft's Bluetooth API so I cannot really help you on that part. As far as I know (but I'm not sure at all), this API is for embedded development only, no ?
Anyway what you can still do is use a BT module that you can connect to your serial port and send AT commands to do some specific actions (like starting an inquiry, connect to a specific Bluetooth device, ...). Of course, this will require that you parse the commands yourself.
|
|
|
|
|
You're right, the Bluetooth syndicate did only produce the specification. I just wish they'd produced a spec for the software API's as well! I think its what has really held back the popularity and take-up of Bluetooth. There are just so many software related problems, many of which wouldn't arisen with a common sw specification.
Microsoft's API is a step in the right direction. They're trying to harmonize all the various drivers out there. Its definitely usable in Windows BTW (but only Win XP SP2) - I'm using it very reliably now. The only problem is it doesn't encompass one of the largest manufacturers of Bluetooth adaptors in the market place (Widcomm).
I have no control over which BT adaptopr is used - its the user's decision - it may be built into their laptop for example. But I need to talk to it whether its compatible with MS API or not.
All I want to do is automatically detect my device, pair it (authenticate it) and enable the virtual serial port. I then look up which port number got assigned to the device and communicate with my device via standard serial port communication. I want to do all this without any user interaction (otherwise they might as well pair the device themselves). My implementation works perfectly with Microsoft's API (plus some registry querying to determine the com port value).
The problem is it looks like I'll need to do the same for Widcomm's API, BlueSolei's, Toshiba's, etc. I was rather hoping somebody might have done this work already for me!
Thanks anyhow
--
The Obliterator
|
|
|
|
|
I am developing Socket application that is going to send packet across network. The data packets contain, STX, Lenght, Opcode, Type, Qualifier, Data[128], CRC, ETX. I was hoping to be able to send the packet via send command. However, I might run into a problem where the que is full and only half my packet goes out. This would cause a sync problem. Is there any way, i can verify how much space is available in the outgoing write buffer.
if( TxQueue.Pop( &temp_packet ) == true )
{
iResults = send( client_socket, (char *)&temp_packet, sizeof(temp_packet), NULL );
if( iResults != sizeof(temp_packet) )
Error = -1;
}
Scott Dolan
Jernie Corporation
Engineering & Manufacturing
Software, Hardware, & Enclosures
|
|
|
|
|
ScotDolan wrote: Is there any way, i can verify how much space is available in the outgoing write buffer
Not that I know of.
It looks like your data is already queued for sending which is good IMO.
I'm assuming you are using non-blocking socket (or it wouldn't be an issue).
Maybe changing the send logic a bit will help...
if( TxQueue.Pop( &temp_packet ) == true )
{
BYTE *pCurSendByte = (BYTE *)&temp_packet;
int iBytesRemaining = sizeof(temp_packet);
while (iBytesRemaining > 0)
{
iResults = send( client_socket, (char *)pCurSendByte, iBytesRemaining, NULL );
if( iResults != SOCKET_ERROR )
{
iBytesRemaining -= iResults;
if (iBytesRemaining > 0)
{
pCurSendByte += iResults;
}
}
else
{
int nWSAErrorCode = WSAGetLastError();
if (nWSAErrorCode != WSAEWOULDBLOCK)
{
Error = -1;
break;
}
}
}
}
This is fairly ok on a separate thread but more efficient would be to use an event object with
WSAEventSelect() to wait on FD_WRITE whenever send() doesn't write all the bytes (or returns
WSAEWOULDBLOCK error) in one shot.
Takes a few extra lines of code
-- modified at 16:37 Thursday 8th February, 2007
*EDIT* Added WSAEWOULDBLOCK error handling
|
|
|
|
|
Also, if using TCP, it's important to receive data efficiently on the other end. send() depends
on the receiving end having buffer room as well!
|
|
|
|
|
Mark,
That code basiclly makes the send function into a blocking function.
I am try to develop a real-time socket applciation(As best as possible). Right now, the send and recv are in a single worker thread. The worker thread also maintains the status of the connection. If disconnects occures, thread will automaticlly reattempt to connect and update status byte within the class notifying calling function the socket is disconnected.
The Blocking function does not work in my application because, i will be waiting on write, when i could receiving data.
This all said, I thinking I might have to create two or three worker threads within this socket class I am developing.
One thread to recv packet and place in the safeque.
One Thread to send packet from safeque.
One Thread to check for FD_CLOSE and FD_CONNECTION events.
Do you think the three thread class would work.
Scott Dolan
Jernie Corporation
Engineering & Manufacturing
Software, Hardware, & Enclosures
|
|
|
|
|
ScotDolan wrote: This all said, I thinking I might have to create two or three worker threads within this socket class I am developing.
One thread to recv packet and place in the safeque.
One Thread to send packet from safeque.
One Thread to check for FD_CLOSE and FD_CONNECTION events.
That works but for even more throughput with minimal threads - one thread for sends and recvs,
one for queueing data for send, and one for handling queued received data works well.
The problem with multiple threads sending and receiving is that it's not guaranteed to be safe
on the same socket. You end up blocking to wait for the other anyway so having more than one
thread for recv and send is IMO unnecessary.
In my socket I/O thread loops, I have an array of events - 1 for termination, 1 for queued send
data, and one for FD_READ/FD_CLOSE events from the socket. Using WaitForMultipleObjects() I wait
on those events (outer loop). When an event is signalled check for terminate (exiting the thread
if signalled), check if FD_READ and if so loop until WSAWOULDBLOCK error, if queued send data
then send like my sample code. After a send check for more queued send packets and set the event
if necessary so next loop will catch it immediately. It works well for real time streaming
data.
|
|
|
|
|
I think i understand you. You basicly wait for events Once you get a read event you start a thread to handle that event and read the fifo. But, before you start that thread you make sure the past current read thead has terminate.
I like the sounds of this socket. Do you have it posted up here. Send me a copy. Please....
Right now, I am going to try simpler versiion of that, I am going to do all my reads and write in the same thread. It will attempt to write one packet, than read one packet and it will never block.. But, I am betting this will not working my application. My new code below.. Let
<br />
case LOOP_CLIENT:<br />
WSAEnumNetworkEvents(client_socket, g_hClientEvent, &NetworkClientEvents);<br />
if( NetworkClientEvents.lNetworkEvents == FD_CLOSE)<br />
{ <br />
printf("Client Socket Closed Message: \n\r"); <br />
WSACloseEvent(g_hClientEvent);<br />
closesocket(client_socket);<br />
WSACleanup();<br />
state = CONNECT_CLIENT;<br />
}<br />
<br />
if( NetworkClientEvents.lNetworkEvents == FD_CONNECT)<br />
{<br />
if (0 != NetworkClientEvents.iErrorCode[FD_CONNECT_BIT]) {<br />
printf("Client Connection Failed: \n\r"); <br />
state = CONNECT_CLIENT;<br />
}else{ <br />
printf("Client Connected Message: \n\r");<br />
state = LOOP_CLIENT;<br />
}<br />
}<br />
<br />
<br />
<br />
if( txbytesremaining == 0 )<br />
{<br />
if( TxQueue.Pop( &temp_txpacket) == true)<br />
{ <br />
temp_txbuffer = (char *)&temp_txpacket; <br />
int txbytesremaining = sizeof(temp_txbuffer); <br />
iResults = send( client_socket, (char *)temp_txbuffer, txbytesremaining, NULL ); <br />
if( iResults != SOCKET_ERROR ) <br />
{ <br />
txbytesremaining -= iResults;<br />
if (txbytesremaining > 0) <br />
temp_txbuffer += iResults;
}else{ <br />
break; <br />
} <br />
}<br />
}else{<br />
iResults = send( client_socket, (char *)temp_txbuffer, txbytesremaining, NULL ); <br />
if( iResults != SOCKET_ERROR ) <br />
{ <br />
txbytesremaining -= iResults;<br />
if (txbytesremaining > 0)<br />
temp_txbuffer += iResults;
}else{<br />
break;
}<br />
}<br />
<br />
<br />
<br />
if( rxbytesremaining == 0 )<br />
rxbytesremaining = sizeof(temp_rxbuffer);<br />
<br />
iResults = recv( client_socket, (char *)temp_rxbuffer, rxbytesremaining, NULL ); <br />
switch( iResults )<br />
{<br />
case 0:<br />
break;<br />
case SOCKET_ERROR:<br />
break;<br />
default:<br />
rxbytesremaining -= iResults;<br />
temp_rxbuffer += iResults; <br />
if( rxbytesremaining == 0 )<br />
{<br />
temp_rxpacket = (INDEPENDENCER_PKT *)temp_rxbuffer;
if( temp_rxpacket.verifyCRC() )<br />
{<br />
m_TcpClientRxPktCount++;<br />
RxQueue.Push( temp_rxpacket );<br />
}else{<br />
m_TcpClientRxPktCrcErrCount++;<br />
}<br />
}<br />
break;<br />
}
<br />
break;
Scott Dolan
Jernie Corporation
Engineering & Manufacturing
Software, Hardware, & Enclosures
|
|
|
|
|