What for ? ODBC is 17 years old .
There are tons of complete samples for ODBC in C and C++ in MSDN (SDK, KB, doc, etc), published since 1993.
You'll never find better than Microsoft code...
|
Perhaps you're right. The reason I'm doing it is I just broke down here a few weeks ago and bought Visual Studio 2008 Pro, and I wanted to tackle something somewhat major to get used to using it. I've been using VC6 for ages it seems, and thought it time to upgrade. The other thing I've been fighting for what seems like forever is UNICODE. I've finally decided to give up and give in to it and use TCHAR and all the truely horrible ugly macros in tchar.h. I'm just worn out and sick and tired of fighting it.
With regard to my initial post about the critical sections, I've been at it in the pits slugging it out with the app and I've determined for absolute certainty that my problem has nothing to do with threads or critical sections.
As I mentioned briefly in my initial post my whole use of threads and critical sections was prompted by my complete inability to successfully create an hourglass cursor during the split second or so that database transactions were occurring. So far this has defied every attempt of mine. And I'm not a beginning Win32 coder by any means. About 10 years ago I had a run in with this problem and I recall solving it I believe by handling the WM_MOUSEMOVE message and calling SetCursor() in that processing, and I believe I was using a static or global flag to test when to show the hourglass or the arrow. I remember thinking at the time that it was pretty ridiculous and awkward, and there had to be a better way; however, I recall it did work, and I never persued the matter further.
The reason I expect I havn't had a run in with this problem sooner is that for desktop app development I almost exclusively use PowerBASIC as it allows me to be much more productive than with C++. With that language though I do strictly Api Sdk coding. However, in that language they have a proprietary keyword 'MousePtr' where you can set it to any of the predefined equates such as hourglass=11 or arrow=1 and it works perfectly. That's why my PowerBASIC program is working and the C++ one not - it isn't anything to do with threads as I first thought.
Where I do a real lot of C++ development though is in Windows CE. And in those Apis there is a similiar situation as with PowerBASIC. There are predefined functions that can be called that are unique to CE that control the shape of the mouse cursor, and they work too.
So, I'm going to fight this today, tomorrow - however long it takes to beat it. I'm going to search the internet, study the docs, experiment - whatever it takes to beat it and however long it takes. If some kind soul out there wants to take pity on my poor stupid miserable self and tell me how to do it I am at a point beyond anger and humiliation and will gratefully accept with absolute humbleness and gratitude the secret hidden combination of Api calls that will turn a cursor into an hourglass and maintain it in that state untill in the fullness of time I see fit to turn it back into an arrow.
I knew this was going to be a problem before I started this project (remembering my experience of ten years ago), and so I studied the docs somewhat carefully on cursors, and noted that they were saying that when the mouse is moved the OS draws the cursor specified for the class when the class was registered, i.e., the hCursor member of the WNDCLASSEX struct. I further noted that this attribute of the window class could be changed using the SetClassLong() function with GCL_HCURSOR as the second parameter, and a valid HCURSOR as the third parameter. This led me to believe I might be able to successfully do something like this...
void TimeConsumingProcedure(lpWndEventArgs Wea)
{
HCURSOR hHourGlass, hArrow;
hHourGlass=LoadCursor(NULL,IDC_WAIT);
SetClassLong(Wea->hWnd, GCL_HCURSOR, (LONG) hHourGlass);
//Do Time Consumming Processing
//..................................................
//Now Done - Show Arrow Cursor
hArrow=LoadCursor(NULL,IDC_ARROW);
SetClassLong(Wea->hWnd, GCL_HCURSOR, (LONG) hHourGlass);
}
I even wrote a whole program to check it out. Here is that program. All there is is a main form with two buttons on it. When you click the top button the cursor is turned into an hourglass, and when you click the second back into an arrow...
//MouseCursors.h
#define IDC_BTN_HOURGLASS 1500
#define IDC_BTN_ARROW 1505
typedef struct WindowsEventArguments
{
HWND hWnd;
WPARAM wParam;
LPARAM lParam;
HINSTANCE hIns;
}WndEventArgs, *lpWndEventArgs;
struct EVENTHANDLER
{
unsigned int Code;
long (*fnPtr)(lpWndEventArgs);
};
//Now Main.cpp
//Main.cpp
#include <windows.h>
#include <tchar.h>
#include "MouseCursors.h"
EVENTHANDLER EventHandler[3];
long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
HWND hCtl;
Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;
hCtl=CreateWindow(_T("button"),_T("Show Hourglass Cursor"),WS_CHILD|WS_VISIBLE,45,25,200,30,Wea->hWnd,(HMENU)IDC_BTN_HOURGLASS,Wea->hIns,0);
hCtl=CreateWindow(_T("button"),_T("Show Arrow Cursor"),WS_CHILD|WS_VISIBLE,45,70,200,30,Wea->hWnd,(HMENU)IDC_BTN_ARROW,Wea->hIns,0);
return 0;
}
long fnWndProc_OnCommand(lpWndEventArgs Wea)
{
HCURSOR hCursor;
switch(LOWORD(Wea->wParam))
{
case IDC_BTN_HOURGLASS:
hCursor=LoadCursor(NULL,IDC_WAIT);
SetClassLong(Wea->hWnd,GCL_HCURSOR,(long)hCursor);
break;
case IDC_BTN_ARROW:
hCursor=LoadCursor(NULL,IDC_ARROW);
SetClassLong(Wea->hWnd,GCL_HCURSOR,(long)hCursor);
break;
}
return 0;
}
long fnWndProc_OnClose(lpWndEventArgs Wea)
{
if(MessageBox(Wea->hWnd,_T("Do You Wish To Exit This App?"),_T("Exit Check?"),MB_YESNO)==IDYES)
{
DestroyWindow(Wea->hWnd);
PostQuitMessage(WM_QUIT);
}
return 0;
}
void AttachEventHandlers(void)
{
EventHandler[0].Code=WM_CREATE, EventHandler[0].fnPtr=fnWndProc_OnCreate;
EventHandler[1].Code=WM_COMMAND, EventHandler[1].fnPtr=fnWndProc_OnCommand;
EventHandler[2].Code=WM_CLOSE, EventHandler[2].fnPtr=fnWndProc_OnClose;
}
long __stdcall fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam,LPARAM lParam)
{
WndEventArgs Wea;
for(unsigned int i=0;i<3 ;i++)
{
if(EventHandler[i].Code==msg)
{
Wea.hWnd=hwnd,Wea.lParam=lParam,Wea.wParam=wParam;
return (*EventHandler[i].fnPtr)(&Wea);
}
}
return (DefWindowProc(hwnd,msg,wParam,lParam));
}
int __stdcall WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
TCHAR szClassName[]=_T("Form1");
WNDCLASSEX wc;
MSG messages;
HWND hWnd;
AttachEventHandlers();
wc.lpszClassName=szClassName; wc.lpfnWndProc=fnWndProc;
wc.cbSize=sizeof (WNDCLASSEX); wc.style=CS_DBLCLKS;
wc.hIcon=LoadIcon(NULL,IDI_APPLICATION); wc.hInstance=hIns;
wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION); wc.hCursor=LoadCursor(NULL,IDC_ARROW);
wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW; wc.cbWndExtra=0;
wc.lpszMenuName=NULL; wc.cbClsExtra=0;
RegisterClassEx(&wc);
hWnd=CreateWindow(szClassName,_T("Form1"),WS_OVERLAPPEDWINDOW,300,200,300,200,HWND_DESKTOP,0,hIns,0);
ShowWindow(hWnd,iShow);
while(GetMessage(&messages,NULL,0,0))
{
TranslateMessage(&messages);
DispatchMessage(&messages);
}
return messages.wParam;
}
After I wrote this program a few weeks ago I thought I had the problem solved. But alas, no!