Frederick2 189 Posting Whiz

Last week I had a major run in with that problem. Perhaps check out this link at www.cplusplus.com...

http://www.cplusplus.com/forum/windows/14189/

I know it doesn't sound like a cursor related thread, that was indeed the cause of the problem. I really can't help you with the issue from the standpoint of MFC because I don't know it or use it, but in nterms of the Win32 Api, your issue involves the cursor set into the Window Class Structure. Basically, to change the cursor you have to LoadCursor() the one you want, then SetClassLong() it into the WindowClass. Then you have to call SetCursor(). This sequence of operations will change the cursor for every window of the class. If for example its your main dialog and you don't anticipate having multiple instances of it running at the same time, then there is no problem. If you specifically want to only change the cursor for tye specific window, then you need in addition to handle the WM_SETCURSOR message.

Frederick2 189 Posting Whiz

You know, sometimes, when things don't work for seemingly no reason at all, it pays to just start over, reboot, whatever. In your case ExMachina, have you considered just deleting the project (saving the source, of course) and starting over? There's almost certainly a bad reference involved somewhere that is messing things up - perhaps something you did in setting up the project. Before doing that perhaps you could try the less drastic solution of just highlighting the misbehaving include file in the solution explorer, and hitting the delete key. A popup will ask if you want to delete the file or simply remove it from the project. Just tell it to remove it. Then shut down VS and restart. Open up the project and re-include the file. Right click on the 'Headers' folder and select 'Add Existing Item', then try again. It might work.

Frederick2 189 Posting Whiz

No, I don't know why you would have to do that, ExMachina. But it was a good idea wasn't it!

Any chance you installed Visual Studio under one log in and are developing under another? Possible rights problems? Just grasping at straws here!

If you copied that file from a CD is it marked as read only??? That ones bit me a few times. As the other knowlegeable fellow said, the development environment has several places it looks for things before crapping out with an error.

I actually just bought VC9 myself recently. All these modern compilers seem to be creating ever more complicated directory setups for a project's files, that's for sure. About my favorite is Dev-cpp. With that I can get a project up and running in about 30 seconds. I can't say that for any of the others, i.e., CodeBlocks, VC6, VC9, etc.

Frederick2 189 Posting Whiz

Well, that's good! Then we know your setup is working.

Did you try specifying the exact path in the #include line, such as...

#include "C:\Documents and Settings\VStudio\MyRecalcitrantHeader.h"

I mean, you shouldn't have to do that, but I'm just trying to figure out what's wrong, i.e., why it won't read a file you claim is there?

Frederick2 189 Posting Whiz

Have you successfully created and ran any project yet? Even a Hello, World! project?

Frederick2 189 Posting Whiz

Well, if you've created a new C++ project/solution, there should be a Solution Explorer visible somewhere on the screen. I believe there's a 'File View' which can be toggled. When that is selected you should see a Tree View Control that lists the various file types you can include in a project. Naturally, C++ projects need a *.cpp file. These will be listed under the 'Source' files node. Under the 'Header' files node are the header fies in your project if there are any. If there aren't then Right Clicking on that node will pop up a context menu where you can either navigate to where some *.h file exists that you want to include in your project, or give you the option of adding a new blank file into which you can type header file type info.

Is this making any sense? Have you gotten that far?

If you have something like this...

#include <iostream.h>
#include "MyHeader.h"

...and the compiler error says it can't find "MyHeader.h", then that means the compiler can't find "MyHeader.h". In other words, if its not in the directory its looking, you'll have to add a explicit path to the file, or put it in with the other source files for the project where the compiler wil find it.

Frederick2 189 Posting Whiz

Just out of idle curiosity I just tested it. Pretty much as I thought. You see, if you have a two dimensional array like test[2][4], then this...

test[1]

will represent the address of the second row. So yes, you can define a function taking a one dimensional array as a parameter (plus a count integer), and have it operate on any row which you pass to it from a two dimensional array. And I'm sure this is a general case true with arrays of higher dimension. I got it working in my test code anyway. Try this...

(piles of warnings you'll have to clean up, unfortunately)

#include <stdio.h>

int Sum1(int iArr[], int n)
{
 int iTot=0;

 for(int i=0;i<n;i++)
     iTot=iTot+iArr[i];

 return iTot;
}

int Sum(int* pInt, int n)
{
 int iTot=0;

 for(int i=0;i<n;i++)
     iTot=iTot+pInt[i];

 return iTot;
}


int main(void)
{
 int i,j;

 int test[2][4] = {{1,2,3,4},{5,6,7,8}};
 printf("Sum=%d\n\n",Sum(&test[1][0],4));
 for(i=0;i<2;i++)
     for(j=0;j<4;j++)
         printf("%u\t\t%d\n",&test[i][j],test[i][j]);
 printf("\n");
 printf("%u\n",test[1]);
 printf("Sum1=%u\n",Sum1(test[1],4));

 return 0;
}
Frederick2 189 Posting Whiz

That's an interesting idea TalGuy. I havn't written any code to test it, but one thing about arrays is the data is stored sequentially. Perhaps write the function to accept a pointer to the data type and the number of records to process, then pass the starting address for the row you wish it to process? Just a thought.

Frederick2 189 Posting Whiz

I put together a C++ version of the basic Inkey function. Its not exact. My intention was to make it exact, but I ran into some excrutiating problems. The Inkey$ function returns a dynamic basic string (allocated by the OLE String Engine). As such, it can contain null characters. I have my own string class, but it isn't based on Ole strings, but rather on Asciiz null terminated strings, and as such I can't embed nulls in the string. Therefore, I wasn't able to return a string from my string class that has a null as the first character, and the extended character code in the 2nd byte (cursor motion keys and so forth). So what I did was create a typedef like so...

typedef struct KEY
{
 bool blnKeyPressed;   //1 byte
 bool blnExtended;     //1 byte
 char ch;              //1 byte
 char code;            //1 byte
}KEY;

Here is my Inkey function which gets passed by reference a KEY struct...

void Inkey(KEY& k)
{
 int ch;

 memset(&k,0,4);
 if(_kbhit())
 {
    ch=getch();
    if(ch==0x00||ch==0xE0)
    {
       k.blnExtended=true,  k.blnKeyPressed=true;
       k.ch='\0',           k.code=getch();
    }
    else
    {
       k.blnExtended=false, k.blnKeyPressed=true;
       k.ch=(char)ch,       k.code=(char)ch;
    }
 }
 else
    k.blnKeyPressed = false;
}

Here is a program that uses it...

//Main.cpp
#include <stdio.h>
#include <conio.h>
#include <string.h>


typedef struct KEY
{
 bool blnKeyPressed;   //1 byte
 bool blnExtended;     //1 byte
 char ch;              //1 byte
 char code;            //1 byte
}KEY;


void Inkey(KEY& k)
{
 int ch;

 memset(&k,0,4);
 if(_kbhit())
 {
    ch=getch();
    if(ch==0x00||ch==0xE0)
    {
       k.blnExtended=true,  k.blnKeyPressed=true;
       k.ch='\0',           k.code=getch();
    }
    else
    {
       k.blnExtended=false, k.blnKeyPressed=true;
       k.ch=(char)ch,       k.code=(char)ch;
    } …
Frederick2 189 Posting Whiz

Don't know if this will help, but these little fixes cause it to run in CodeBlocks without errors or warnings....

// ASCII-getche
#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <string>
#include <stdlib.h>

using namespace std;

int main(void)
{
 system ("color 0a");
 int c=0;
 char inp;
 inp=' ';    //Since you are saying inp is a char, give it a char
 do
 {
     system("CLS");
     cout << "\n\n\n\n\n\tThis program produces ASCII code for any key pressed.";
     cout << "\n\n\n\n\n\tChar : " << inp << " ASCII: " << c <<"\n\n\n\tEsc to Exit,\tPresskey a key: ";
     c = getche();  //* assign ASCII code to c
     inp=c;    // CHR$ from ASCII     if extended, c=0
     if(c==0)
     {
      c=getche();
      inp=(char)NULL;  //tell it to consider NULL a char, i.e., the NULL char
     }
   } while (c != 27);    /* ESC to escape*/
   cout << "\n\n\n\tBye\n\n\n";
   getch();
}
Frederick2 189 Posting Whiz

I've been using first eVC++ 3 and now eVC++ 4 for about 10 years. They're certainly absolutely free.

There is very, very little difference coding for Win CE and coding Win32. As others have said very well, its good to have a good grasp of C & C++. Then you can code for anything.

Geez! I think the Sdks you have to download and install for each seperate piece of hardware are probably free too. At least for the devices I code for you can download the Sdks from their web site. However, if you want a real unit to test it on you'll need to beg, borrow, steal, or buy one!

Here about a month ago I had to finally break down and fork over $550 bucks for VS 2008 Pro. The units I'll be coding for in the future run Windows Moblie and apparently the free eMbedded VC++ 4.0 won't handle that.

I'll tell you what my issues are with this stuff. I really bust my butt trying to code excellent applications for the handheld data collection instruments we use for mission critical information in my organization, and the life expectancy of any particular piece of hardware, that is, not how long it will last but how long the manufacturer will continue to produce and support it, is really, really small. So what that means is that you need to be constantly ready to port your code to completely different hardware. Therein is the …

Salem commented: Nice post. +36
Frederick2 189 Posting Whiz

Thanks for the kind words Yonghc.

I actually followed with interest your recent thread on console input. That's why I thought I'd finally mention the Win32 Api functions to you because it seemed you might not be aware of them.

Anyway, here is an amazingly short little sample for you that ought to compile & run OK with your newly acquired CodeBlocks. I have that also, but I just tested this quick with VC++6; I'm fairly certain it will work OK with CodeBlocks.

Its a standard Win32 console mode program with no MFC (I guess with CodeBlocks I didn't have to tell you that - it matters with Visual Studio). It displays both keypresses and mouse coordinates as you type or move the mouse. Also, it displays left or right mouse button clicks. I didn't code mouse wheel movements, so that data is garbage. You'll probably have fun figuring it out. Here it is...

#include <windows.h>
#include <stdio.h>

int main(void)
{
 HANDLE hStdInput,hStdOutput;
 INPUT_RECORD ir[128];
 UINT blnLoop=TRUE;
 DWORD nRead;
 COORD xy;
 UINT i;
 
 hStdInput=GetStdHandle(STD_INPUT_HANDLE);
 hStdOutput=GetStdHandle(STD_OUTPUT_HANDLE);
 FlushConsoleInputBuffer(hStdInput);
 while(blnLoop==TRUE)
 {
   if(WaitForSingleObject(hStdInput,3000)==WAIT_TIMEOUT)
      blnLoop=FALSE;  //3 secs
   else
   {
      ReadConsoleInput(hStdInput,ir,128,&nRead);
      for(i=0;i<nRead;i++)
      {
          switch(ir[i].EventType)
          {
           case KEY_EVENT:
             if(ir[i].Event.KeyEvent.wVirtualKeyCode==VK_ESCAPE)
                blnLoop=FALSE;
             else
             {
                xy.X=0;xy.Y=0;
                SetConsoleCursorPosition(hStdOutput,xy);
                printf
                (
                 "AsciiCode = %d: symbol = %c\n",
                 ir[i].Event.KeyEvent.uChar.AsciiChar,
                 ir[i].Event.KeyEvent.uChar.AsciiChar
                );
             }
             break;
           case MOUSE_EVENT:
             xy.X=0, xy.Y=1;
             SetConsoleCursorPosition(hStdOutput,xy);
             printf
             (
              "%.3d\t%.3d\t%.3d",
              ir[i].Event.MouseEvent.dwMousePosition.X,
              ir[i].Event.MouseEvent.dwMousePosition.Y,
              ir[i].Event.MouseEvent.dwButtonState
             );
             break;
          }
      }
   }
 };
 
 return 0;
}


/*
WAIT_ABANDONED   = 128
WAIT_OBJECT_0    = 0
WAIT_TIMEOUT     = 258

Process returned 0 (0x0)   execution time …
Frederick2 189 Posting Whiz

The problem is finally solved, and it had nothing to do with threads. The problem stemmed from my unbelievable failure to understand how to toggle the mouse cursor between an hourglass and an arrow when intensive processing had to occur. If anyone ever has that problem, the critical steps are as follows...

1) Get handle of cursor you want;
2) Set it in the REGCLASSEX struct with SetClassLong()
3) Call SetCursor(hDesiredCursor) to change cursor.

It could easily be made into a little utility function like so...

void MousePtr(HWND hWnd, HCURSOR hDesiredCursor)
{
 SetClassLong(hWnd,GCL_HCURSOR,(long)hDesiredCursor);
 SetCursor(hDesiredCursor);
}

A great deal of documentation on this issue suggests that the WM_SETCURSOR message must be handled to accomplish this, but that is not so.

Frederick2 189 Posting Whiz

I just checked that one out and it does look like Inkey. I wasn't aware of it. I possibly could have used that years ago in a project I did.

Anyway, with the Win32 console functions you would be able to do mouse stuff too. I've worked with that more than the keyboard stuff. Yes, all those functions work with CodeBlocks, Dev-Cpp, VC6-9, etc.

Frederick2 189 Posting Whiz

Hi yonghc,

If you need the exact functionality of the Inkey function as its usually implemented in various BASIC dialects, then you might want to look at the Win32 Console Api. To the best of my limited knowledge, none of the C or C++ libraries provide this exact functionality. It has been my experience at least that all the stdio or conio functions 'block' awaiting some event such as hitting a key. This is not how Inkey traditionally worked. In the DOS world at least (you had mentioned QuickBasic), Inkey was probably implemented by checking a flag in the keyboard registers, and immediately returned and didn't block.

The Windows Console Api includes functions such as ReadConsoleInput() and PeekConsoleInput() that could be used to create an exact duplication of how Basic's Inkey works.

As you know, using these techniques, you'll have the keypress before it is displayed, and you can decide whether to disgard it or use it.

Frederick2 189 Posting Whiz

I have a general question about threads prompted by something strange I'm seeing in an application I developed involving ODBC access to Microsoft Access and SQL Server databases. Let me present the context of the problem first. I have been developing some tutorials on ODBC database access in two different languages, e.g., C++ and PowerBASIC. The programs are GUI apps in pure Sdk style. The way I created the demonstration programs is I created a main window with four buttons on it. When the 1st button is pressed the program scours the registry for SQL Driver information and opens up a scrollable output screen where all the registered ODBC drivers plus their attributes are listed.

Pressing the second button dumps a small sample Microsoft Excel worksheet to another output screen using ODBC.

Pressing the 3rd button creates a Microsoft Access database, creates a table within the database, inserts a few sample records in the database, then creates the output screen and displays diagnostic info and the records added.

The fourth button does the exact same thing as the third except with either Sql Server Express or MSDE.

The program is designed so that each button press creates a new output window, and if you repeatedly click a button, instead of creating a new database, records are simply added to the one created on the first button press. Each output window takes care of its own memory and cleanup.

In the various button press procedures I …

yonghc commented: Laudable effort at sharing very useful codes. However, the mouse movement codes are not working with CODEBLOK yet. +1
Frederick2 189 Posting Whiz

Hope somebody else can help you with that Goody. I simply don't use the Windows Dialog Engine at all. I'm not absolutely sure, but I believe the same general principals will be involved as in the code I showed. Basically, when you click a button in a window (whether it be a CreateWindowEx() window or a window created by the Windows Dialog Engine), the focus will be transferred from the edit box with focus, to the button. This activity is a complex one in that it involves many messages. First you'll have various mouse messages sent to the button. Then you'll have various kill focus & set focus messages. None of these are going to occur within your dialog procedures, and only by utilizing these messages will you be able to accomplish what you described you want to accomplish. So, if you insist on continuing what you are trying to do, you are going to have to find out how you are going to do it within the framework you have chosen to use, and that appears to be the Windows Dialog Engine.

In my opinion use of Dialog Boxes for major and complicated user interfaces - esapecially ones involving extremely unusual behavior such as you are trying to implement, is a very bad idea. While the code I provided might seem complicated, it is my opinion that if you ever achieve this within the framework of the Windows Dialog Engine, your final code will be much, much worse. …

Frederick2 189 Posting Whiz

Felt bad about providing a solution in another language in a C++ forum, so here it is in C++. First the include, then Main.cpp. There are about five edit controls. Set the focus in one of them, then click the button at top.

//WinTypes.h
#ifndef WINTYPES_H
#define WINTYPES_H

typedef struct    WindowsEventArguments
{
 HWND             hWnd;
 WPARAM           wParam;
 LPARAM           lParam;
 HINSTANCE        hIns;
}WndEventArgs,    *lpWndEventArgs;


struct EVENTHANDLER
{
 unsigned int    Code;
 long            (*fnPtr)(lpWndEventArgs);
};

#endif
//Main.cpp  - GoodysProblem
#include <windows.h>
#include <tchar.h>
#include "WinTypes.h"
#define BTN_BUTTON1 2000
#define IDC_EDIT    3000
EVENTHANDLER EventHandler[3]; 
WNDPROC fnOldEditProc;


long __stdcall fnEditSubClass(HWND hwnd, unsigned int msg, WPARAM wParam, LPARAM lParam)
{
 if(msg==WM_KILLFOCUS)                           //This procedure is a 'sub class 'hook'
 {                                               //into the internal 'edit' class window
    SetWindowLong(GetParent(hwnd),0,(long)hwnd); //procedure within windows.  Its purpose
    return 0;                                    //is to 'hook' WM_KILLFOCUS messages.  When
 }                                               //it gets one it persists it to the main
                                                 //window's .cbWndExtra bytes.
 return CallWindowProc(fnOldEditProc,hwnd,msg,wParam,lParam);
}


long fnWndProc_OnCreate(lpWndEventArgs Wea)           
{
 HWND hCtl;
                                                     
 Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance; 
 hCtl=CreateWindow
 (
   _T("button"),
   _T("Button #1"),
   WS_CHILD | WS_VISIBLE,
   70,20,150,30,
   Wea->hWnd,
   (HMENU)(BTN_BUTTON1),
   Wea->hIns,
   NULL
 );
 for(unsigned int i=0;i<6;i++)
 {
     hCtl=CreateWindowEx
     (
       WS_EX_CLIENTEDGE,
       _T("edit"),
       _T(""),
       WS_CHILD|WS_VISIBLE,
       10,70+40*i,265,25,
       Wea->hWnd,
       (HMENU)(IDC_EDIT+i),
       Wea->hIns,
       0
     );
     fnOldEditProc=
     (WNDPROC)SetWindowLong
     (
       hCtl,
       GWL_WNDPROC,
       (LONG)fnEditSubClass
     );
 } 

 return 0;                                             
}


long fnWndProc_OnCommand(lpWndEventArgs Wea)     //When you press the button the text below is put      
{                                                //in the edit control whose hWnd is stored at offset     
 switch(LOWORD(Wea->wParam))                     //zero in the .cbWndExtra bytes.  It got put there
 {                                               //when one of the edit controls lost focus as picked
  case BTN_BUTTON1:                              //up in the sub class …
Frederick2 189 Posting Whiz

Ahh! goody, sorry about that! You are right. It doesn't work. I'm afraid the solution is a bit more complex. Basically, when a textbox has the focus and you click some other control such as a button, the edit control will lose the keyboard focus and windows will send it a WM_KILLFOCUS event just before it changes the focus to whatever. The problem with that is that in order for you to intercept that WM_KILLFOCUS message received by the edit control just about to lose the keyboard focus, you need to have subclassed the edit control itself (the window procedure of edit controls is in Windows). I wrote a quick PowerBASIC program to test out my theory and it worked perfectly. I put a button at the top of the Form, and generated five or six edit controls within a for loop in the WM_CREATE handler. Within that for loop I subclassed all the edit controls. Within the subclass proc I tested for WM_KILLFOCUS messages. When I got one I stored the handle of the edit control receiving a WM_KILLFOCUS message at offset zero within four extra .cbWndExtra bytes I allocated in the main Window's class structure. When you click the button at the top of the form a text string is written to whatever of the six edit controls had the focus befoire you clicked the button. Here is the PowerBASIC SDK style code. If you are an Api coder it will be quite clear to you, as the …

Frederick2 189 Posting Whiz

Yea, try this...

GetFocus  The GetFocus function retrieves the handle to the window that has the keyboard focus, if the 
          window is associated with the calling thread's message queue. 

HWND GetFocus(VOID)
 
Parameters  This function has no parameters. 

Return Values

The return value is the handle to the window with the keyboard focus. If the calling thread's message 
queue does not have an associated window with the keyboard focus, the return value is NULL. 

Remarks

Even if GetFocus returns NULL, another thread's queue may be associated with a window that has the keyboard focus. 

Use the GetForegroundWindow function to retrieve the handle to the window with which the user is currently working. You can associate your thread's message queue with the windows owned by another thread by using the AttachThreadInput function.
Frederick2 189 Posting Whiz

Here's some additional info...

The MAKELONG macro creates an unsigned 32-bit value by concatenating two given 
16-bit values. 

DWORD MAKELONG
(
  WORD wLow,  // low-order word of long value
  WORD wHigh  // high-order word of long value
);
 
Parameters

wLow     Specifies the low-order word of the new long value. 
wHigh    Specifies the high-order word of the new long value.

BN_CLICKED  The BN_CLICKED notification message is sent when the user clicks a 
            button. The parent window of the button receives this notification 
            message through the WM_COMMAND message. 

BN_CLICKED
 
idButton = (int) LOWORD(wParam);    // identifier of button 
hwndButton = (HWND) lParam;         // handle to button

So you would need...

SendMessage(hParent, WM_COMMAND, MAKELONG(idButton, BN_CLICKED), hButton);

where hParent is the parent or container control of button in question and idButton
is the identifier of button from CreateWindow().  If you have either the hWnd of
button or control id you can get the other from either GetCtrlID() or GetDlgItem().
The parent of a control can be gotten from GetParent().

Also check out BN_CLICK message.

Frederick2 189 Posting Whiz

Sure, buttons are windows. In Windows, everything's a window except those things that aren't windows!

You could use SendMessage to the hWnd of the button with the BN_CLICKED notification - I believe - in the LOWRD of wParam. Please check out that part. There are macros to position various 16 bit quantities in either the low or hi word of wParam.

Frederick2 189 Posting Whiz

Worked on that big time a few years back. What I specifically wanted to do was see if I could use printf from the msvcrt.dll in a GUI process. I expect WriteConsole would be easy, but I wanted printf, and that's trickier than h***. And to make matters worse, I wanted to do it in PowerBASIC. First I figured out how to do it in C, then I rewrote it in PowerBASIC. I'll include both programs. I don't expect you're interested in the PowerBASIC program (the 2nd), but that's where all the comments are. 1st the C++ program, as compilable in VC9...

#include <windows.h>
#include <stdio.h>          //contains _fdopen
#include <fcntl.h>          //contains equate _O_TEXT
#include <io.h>             //contains declare for _open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE),_O_TEXT);
#define  IDC_BUTTON  1500

long __stdcall fnWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam) 
{ 
 HWND hButton;
 HINSTANCE hIns;
 int hCrt,iWeight;
 FILE *hf;	

 switch (msg)                                                            
 {                                                                       
  case WM_CREATE:
    hIns=((LPCREATESTRUCT)lParam)->hInstance;  
    hButton=CreateWindow("button","Show Console",WS_CHILD|WS_VISIBLE,110,65,200,25,hwnd,(HMENU)IDC_BUTTON,hIns,0);
    return 0;     
  case WM_COMMAND:
    if(LOWORD(wParam)==IDC_BUTTON)
    {
       AllocConsole();
       hCrt=_open_osfhandle((long)GetStdHandle(STD_OUTPUT_HANDLE),_O_TEXT);
       hf = _fdopen( hCrt, "w" );
       _iob[1]=*hf;
       iWeight=210;
       printf("My Name Is Fred And I Weight %u Pounds!\n",iWeight);
    }
    return 0;
  case WM_CLOSE:
    DestroyWindow(hwnd);
    PostQuitMessage(WM_QUIT);
    return 0;                                      
 }                                                                       
                                                                         
 return DefWindowProc(hwnd,msg,wParam,lParam);                           
}


int __stdcall WinMain(HINSTANCE hIns,HINSTANCE hPrevIns,LPSTR lpszArgument,int iShow)
{                                   
 char szBuffer[64];       
 WNDCLASSEX wc;                    
 MSG messages;                     
 HWND hWnd;                        
 
 strcpy(szBuffer,"Console_Output");
 wc.lpszClassName=szBuffer   ;                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_BACKGROUND;   wc.cbWndExtra=0;
 wc.lpszMenuName=NULL;                        wc.cbClsExtra=0; 
 RegisterClassEx(&wc);
 strcpy(szBuffer,"GUI Console Output With C Runtime Library From C!");  
 hWnd=CreateWindow("Console_Output",szBuffer,WS_OVERLAPPEDWINDOW,500,500,440,200,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
  TranslateMessage(&messages);
  DispatchMessage(&messages);
 }

 return messages.wParam;
}

...and here's the PowerBASIC program with comments..

'Program demonstrates how to restore …
Frederick2 189 Posting Whiz

( (void (*)()) vptr[0] )();

This term...

((void(*)())

is a cast prefaced in front of this function pointer call...

vptr[0] )();

The function pointer call is calling a function at this address...

vptr[0]

...and the function itself is such that it takes no parameters, i.e., 'void', and returns nothing, i.e., return is void.

The cast in front of this function address is simply necessary to inform the compiler that,

a) it is a function pointer call that returns void;
b) it uses __cdecl;
c) it is a function pointer call and there are no parameters.

Frederick2 189 Posting Whiz

Spent a lot of time working with that some time ago. Here's a daniweb link...

http://www.daniweb.com/forums/thread144510.html

Also, here's a link to some of my tutorials using C, C++ and PowerBASIC where I pretty much take COM memory apart and look close at VTables, VTable pointers, function pointers, calling class member functions using function pointers derived from VPtrs, and the like...

http://www.jose.it-berater.org/smfforum/index.php?board=362.0

Frederick2 189 Posting Whiz

According to marco93 there are piles of tutorials out there already on ODBC. If you do a search on ODBC (Open Database Connectivity) you'll find hundreds of links. So the answer is emphatically YES. I was going to post a tutorial on it too but I won't bother now. See...

http://www.daniweb.com/forums/thread214199.html

Frederick2 189 Posting Whiz

Well, maybe code snippets would actually be better. I hadn't really intended paragraph upon paragraph of prose - just some comments here & there in the code. I wouldn't mind attaching files though if that's possible.

Frederick2 189 Posting Whiz

Is there a link somewhere that explains how to post tutorials? I have one I'd like to post (it shows how to use direct ODBC for enumerating ODBC drivers, connecting to Excel, Access, and SQL Server Express), and don't know how to do it. Would it need to be reviewed by anyone?

Frederick2 189 Posting Whiz

It'll take exactly 10,000 hours.

That's what this article says, if my memory serves...

http://money.cnn.com/magazines/fortune/fortune_archive/2006/10/30/8391794/index.htm

Hardest thing I ever tried to do was learn how to pick a five string banjo. With that, you've got three fingers, and five strings. The notes sound really sharp and fast, and if you make the slightest mistake, you'll hear it. And everyone else will too. And for up tempo picking, you've got to pick about ten notes per second. They've all got to be in perfect timing. And that's just the picking hand. As for the fretting hand....

I'll leave that to your imagination.

Computer programming is a little easier than that, but not much. I started with Fortran in the 1970s, C in the 80s, VB in the 90s, back to C, C++ and PowerBASIC in the 2000s. I've only scratched the surface of what can be done. The nice thing I'll say about programming though, is that even if you only know a little bit, you can do much better with the computer than folks whose sole method of interaction is visual GUI drag and drop type stuff. Using code you can deal with the beaste on its own terms.

Frederick2 189 Posting Whiz

Thanks Salem & firstPerson. That was it. I copied the 1st line of a procedure in a .cpp file to a .h file for a prototype, and forgot to put a semicolon at the end.

Frederick2 189 Posting Whiz

Only have Visual Studio 2008 about a week but just ran into something inexplicable to me. This include file (and others like it)...

//DoTestData.h
#ifndef DOTESTDATA_H
#define DOTESTDATA_H

unsigned int iCreateDB(TCHAR*);
unsigned int blnMakeTable(SQL&);   
int GetRecordCount(SQL&, unsigned int&);
unsigned int blnInsert(SQL&, TCHAR**, unsigned int&, HWND, int);
unsigned int blnDumpData(SQL&, TCHAR**, unsigned int&, HWND);
void btnAccess_OnClick(lpWndEventArgs);
void btnSqlServerExpress_OnClick(lpWndEventArgs); 
void btnSqlServerMSDE_OnClick(lpWndEventArgs);
 
#endif

...generate this error...

c:\code\vstudio\vc++9\sqldemo\DoTestData.h(5) :
error C2144: syntax error : 'unsigned int' should be preceded by ';'

Why in the world should I have to place a semicolon before a line? At a total loss as to why I would have to place a semicolon before a line but wanting the darn thing to compile I thought, "Well, its ridiculous, but if it wants one before the line I'll put it there and see what happens!" Sure enough, it compiled! (Runs too). Here is the changed code with a semicolon before the 'unsigned int'. What in the world is going on???

//DoTestData.h
#ifndef DOTESTDATA_H
#define DOTESTDATA_H

;unsigned int iCreateDB(TCHAR*);
unsigned int blnMakeTable(SQL&);   
int GetRecordCount(SQL&, unsigned int&);
unsigned int blnInsert(SQL&, TCHAR**, unsigned int&, HWND, int);
unsigned int blnDumpData(SQL&, TCHAR**, unsigned int&, HWND);
void btnAccess_OnClick(lpWndEventArgs);
void btnSqlServerExpress_OnClick(lpWndEventArgs); 
void btnSqlServerMSDE_OnClick(lpWndEventArgs);
 
#endif
Frederick2 189 Posting Whiz

Here's WaitForSingleObject()

WaitForSingleObject

The WaitForSingleObject function returns when one of the following occurs: 

The specified object is in the signaled state. 

The time-out interval elapses. 

DWORD WaitForSingleObject
(
  HANDLE hHandle,        // handle to object to wait for
  DWORD dwMilliseconds   // time-out interval in milliseconds
);
 
Parameters

hHandle 
Handle to the object. For a list of the object types whose handles can be specified, see the following Remarks section. 

Windows NT: The handle must have SYNCHRONIZE access. For more information, see Standard Access Rights. 

dwMilliseconds 
Specifies the time-out interval, in milliseconds. The function returns if the interval elapses, even if the object's state is nonsignaled. If dwMilliseconds is zero, the function tests the object's state and returns immediately. If dwMilliseconds is INFINITE, the function's time-out interval never elapses. 
Return Values
If the function succeeds, the return value indicates the event that caused the function to return. This value can be one of the following. 

Value Meaning 

WAIT_ABANDONED The specified object is a mutex object that was not released by the thread that owned the mutex object before the owning thread terminated. Ownership of the mutex object is granted to the calling thread, and the mutex is set to nonsignaled. 
WAIT_OBJECT_0 The state of the specified object is signaled. 
WAIT_TIMEOUT The time-out interval elapsed, and the object's state is nonsignaled. 


If the function fails, the return value is WAIT_FAILED. To get extended error information, call GetLastError. 

Remarks
The WaitForSingleObject function checks the current state of the specified object. If the object's …
Frederick2 189 Posting Whiz

These types of issues fall under the canopy of 'Windows Synchronization Objects' and lead into such topics as Mutexes (Mutual Exclusion Synchronization Objects) and semiphores. In the program I posted yesterday there was a very simplistic method of not allowing the user to launch additionl threads until the one underway was finished by simply disabling the button control that starts the thread until the thread is finished, and then re-enabling it. If you want something more sophisticated, such as the ability to cancel mid way through, then you need the signaling potentials of the above listed sychronization topics.

I'm personally just beginning to use these things - not so much mutexes, but threads & such. Up to this point most of my apps are single threaded. When lengthy procedures are running I usually just change the cursor to an hourglass or use a progress bar, and most of my computations with the speed of modern computers only take several seconds.

However, if you want to get into this the last chapter of Brent E. Rector and Joseph M. Newcommer's 'Win32 Programming' book cover Synchronization objects in pretty gory detail. One place I've used mutexes successfully is I create one based on a file name chosen by the user in an open file dialog box, and I don't let the user open a second invocation of the same file. This I do in my Windows CE data recorder programs. The object is in a signalled state and that can …

Frederick2 189 Posting Whiz

Yes, Seakayaker, you need another thread for that. I'll list all the code for a small program below that should show all the ingredients in a GUI example. The context for this particular program is that I wanted to add a button to one of my Windows CE data collector programs that when clicked would start a thread to collect Gps lats & longs every second for anywhere from 10 to 180 seconds. I didn't want this to interfere with the other data collection activities and so I wanted a 'worker' thread in the background running while the GUI was being used for other purposes.

The program below is VC++ 6 but should compile with anything. Save tyhe file as Main.cpp if you want. The program opens an output.txt log file that will help you see what is going on. When you click the button a thread is created and a Windows timer started that runs for ten seconds and places a message in the listbox every second.

#include <windows.h>
#include <stdio.h>
#include <time.h>
#define IDC_LISTBOX   2000
#define IDC_BUTTON    2005
FILE*                 fp;


typedef struct GPSDATA
{
 double               dblLatitude;
 double               dblLongitude;
}GpsData;


typedef struct        WindowsEventArguments               
{
 HWND                 hWnd;                               
 WPARAM               wParam;                             
 LPARAM               lParam;                             
 HINSTANCE            hIns;                               
}WndEventArgs, *lpWndEventArgs;


void GetRawGps(double r_tic, double& dblLatitude, double& dblLongitude, double r_elv, double r_pdop, double r_ehe, double r_quality)
{
 srand(time(NULL));
 dblLatitude=rand();
 dblLongitude=rand();
}


void __stdcall fnTimerProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 
{
 double dblLatitude=0.0,dblLongitude=0.0,r_tic=0.0,r_elv=0.0,r_pdop=0.0,r_ehe=0.0,r_quality=0.0;
 unsigned int iNumReadingsDesired,iNum,iReturn=0;
 CRITICAL_SECTION m_memLock;
 GpsData* ptrGpsData=NULL;
 char szBuffer[16];
 HANDLE …
Frederick2 189 Posting Whiz

Thanks Salem. I'll try that. I'm new to the latest version of Visual Studio (just bought 2008 Pro), so I'm trying to find the best way to do things yet.

Frederick2 189 Posting Whiz

It seems even if I place

#define _CRT_SECURE_NO_WARNINGS

at the top of my C++ source files, if the warning level is set to 3 or 4 I still get all the warnings. Is this the way it is supposed to be? I like to have my warning levels set fairly high to help me catch stuff, but I'd like to eliminate the strcpy and other stuff that brings up these warnings. Any suggestions?

Frederick2 189 Posting Whiz

Just a couple weeks ago I added some code to one of my Windows CE data recorder programs that my organization uses, and what the 'add on' does is record Gps satellite latitude & longitude readings into a data file. The program itself is for recording field data on trees. However, we wanted to have the Gps coordinates saved along with each plot. There was an external library in the form of a dll that I statically linked to, and it exported several functions that I could call to obtain gps coordinates when I wanted them. I didn't want the GPS data collection to interfere with the tree data collection, so I started a seperate thread of execution to collect a user specified number of gps points for averaging while the user was entering other data. What I did was create a timer loop that ran for X number of seconds and collected a point every second. It updated the count into some user memory, and when the count was complete it droped out of the while loop & ended the thread. It works wonderful. Doesn't tie up the machine or anything. It even pops up a window that the user can minimize and go about other things if he/she doesn't want to watch the every second lat/long readings, and the window destroys itself when done. If you want more details let me know.

Frederick2 189 Posting Whiz

Sounds like you should create a struct to contain all the globals and simply pass the address of the struct variable. If the struct definition is in a header file included where need be you would be able to use it that way. Globals can always be eliminated. Something to keep in mind.

Frederick2 189 Posting Whiz

It would be good to mark the thread as solved if you are indeed satisfied?

Frederick2 189 Posting Whiz

The bad news is that GUI programming (graphical user interface, i.e., program appears in a window - not output to a console screen) is very different from console mode programming. If you are just starting out it would be a good idea to stick with the console for awhile. To move into GUI programming you have a number of choices in C++ but they are all somewhat taxing to learn. You either need to learn a class framework to create windows, or learn the Windows Api and to Sdk style coding. If you have Dev C++ there is a template installed you can look at that creates a window. Open Dev C++ and go to the File menu and choose New Project ... then from the templates pick 'Windows Application'. It will come up with a file for you to save and you can save it as 'Project1' and Main.cpp. Compile & run that and you'll see a window with nothing in it. To write text to that window like you would write text to a console screen you would use the Api functions TextOut() or DrawText(). Look over the code & you'll see what's involved.

Here I modified the Project1, 'Windows Application' code of the default template to add a WM_PAINT handler for you to show how to output text. Everything is the same as the template except for a few lines in the Window Procedure. Replace the default in your code editor with this & run it.

Frederick2 189 Posting Whiz

However, there are a couple of books that describe how vtables typically work internally, given the full understanding that exact details will vary from compiler to compiler. In my experience, knowing the ways polymorphism can be implemented will help solidify your understanding of the big picture and give you more confidence, but unless you write C++ compilers you're not likely to use that knowledge in real world code.

The little pictures with boxes and arrows pointing about always left me a bit unsatisfied. I felt that as a coder I had to be able to doodle around with the addresses and pointers and so forth just to prove to myself I knew what was going on in memory, and that I was capable of the abstruce thought processes necessary to understand it all. Here is a disuussion I started on this topic quite some time ago, and was most appreciative that a very knowlegeable member helped me out...

http://www.daniweb.com/forums/thread144510.html

Some time after that discussion I wrote a few tutorials on my explorations of VTABLES and COM memory layout, and they can be found here...

http://www.jose.it-berater.org/smfforum/index.php?PHPSESSID=0b27761d455031d08871f877a1448ac9&board=362.0

While this latter is in a PowerBASIC oriented forum, most of the code in question is C++ code.

Frederick2 189 Posting Whiz

This whole thing is a literal string....

"INSERT INTO characters(Name, CID, Age, Char_Strength, Char_Speed, Char_Endurance, Char_Aim, Char_RunningEndurance, Blackmarket, Business, Electronics, Food, Misc, Money, Inventory_room, Model, Title) VALUES ('Test Name', '45264', 20,'20','20','20','20','20','1','1','1','1','1',599,500,'lol','Lol')"

It is a SQL Insert statement. If you want to get the value held in the string variable 'Test' into the table, you have to get the characters of the string variable into the above character string where 'Test Name' is. Perhaps parsing it or concatenating it together. In database programming such as this, one typically builds these SQL statements from the parts of the statements themselves such as "INSERT INTO characters(..." and from the various variables one has in memory in one's program.

Frederick2 189 Posting Whiz

I have to make a confession; I'm just not that good with the Windows Dialog Engine and almost never use it to do anything. Rather, I CreateWindow() all my windows. So, I might not be the best source of help here. However, here is a thought that may give you some ideas. You apparently need to get that dialog painted somehow quickly in response to something happening. The fact is the WM_PAINT message is a very low priority message in Windows, and what the operating system prefers to do rather than spending a lot of effort repainting windows is accumulate invalid regions within internal structures until the window desperately needs to be repainted, and then sends one WM_PAINT message with perhaps a great deal of 'dirty bits' in its 'Invalid Region'. That's probably why you are only getting one WM_PAINT at the end of the processing instead of one at the beginning and one at the end. So, like ebookfinder said, somehow you're going to have to force a WM_PAINT message both before and after. With CreateWindow() windows that is usually done with the InvalidateRect(), UpdateWindow() sequence. I expect that would work with dialogs, but I wouldn't bet my life or paycheck on it. Hope tis helps.

Frederick2 189 Posting Whiz

If I were to code something like that I'd have two window classes registered, i.e., a main program window that in your case apparently has the button on it, and a display/output/status window that appears when the button is clicked and is perhaps closed by the user ( [X] ) after processing is done. In such a case I'd have two window procedures in my program. I'd create the display/output/status window through a CreateWindowEx() call and at that point I'd have the hWnd of that window which I'd likely save one way or another because it needs to persist. Having that hWnd you would be able to get a device context for it and draw to it at any time and the results would be all but instantaneous. A fancier and more complex way to go about it would be to define a custom message to SendMessage() to the status window, and in either the wParam or lParam you could include a flag that could be checked when the status window receives the message. It could then do an InvalidateRect() / UpdateWindow() call to cause a specific message to be TextOut()'ed during the WM_PAINT. No code is shown so I'm not exactly sure what problem you are having, but what you are trying to do is quite easily doable.

Frederick2 189 Posting Whiz

Can't imagine why you are using GetDC(), ReleaseDC() in WM_PAINT. That isn't done. There is no reason whatsoever to do that.

Frederick2 189 Posting Whiz

Microsoft Excel is an out of process COM server and COM interfaces can be used to read/write anything from it or out of it.

In a pinch I'd use ODBC direct and connect to the Microsoft Jet Database Engine. I don't believe many people know this but the aformentioned can minipulate Excel *.xls files in addition to Microsoft Access databases. Once you know how to use ODBC direct its very easy to do. But not many folks know ODBC direct.

I've posted examples of how to do this in the PowerBASIC forums. Perhaps I ought to translate that to C++ & post it somewhere. Afterall, Excel is widely used.

Here's a link to a lot of info about Excel in the PowerBASIC forums. With that language there is a built in COM implementation that can easily read/write Excel spreadsheets. However, the COM techniques rely on Excel being installed on the computer where the program is running. The ODBC techniques do not. About midway through this link I have ODBC code posted to do this. Translating it to C/C++ would be easy.

http://www.powerbasic.com/support/pbforums/showthread.php?t=13881

Just one more thought. I believe you could probably also use Ado to connect to Excel. Never done it myself though.

Frederick2 189 Posting Whiz

Sort of, the first one simply tells the system to request a repaint given those conditions. The UpdateWindow(hWnd); function on the other hand, allows you to request an update when you need one. If you make some changes to the window, where you don't change the size, then you will need to request a repaint yourself.

Exactly. In some types of scroll code, for example, when the user clicks the scroll bar up or down arrows, you may wish to entirely repaint the window to change what is displayed. A typical way of doing that would be to use the InvalidateRect() function followed by the UpdateWindow() function to force a WM_PAINT message. In the WM_PAINT processing different lines of text or whatever would be drawn.

I have Ivor Horton's VC++ 6 (around 2000 or so) "Beginning C++ 6" book. In that edition anyway there was one chapter devoted to Sdk style Windows programming. The rest of the book was all MFC.

If your only interest is to become acquainted with Sdk style coding for Windows then quickly move on to MFC or .NET (various class frameworks), then Ivor's book would be enough. However, if you wish to really delve deeper into programming Windows with the raw Api, then you need to acquire Charles Petzold's "Programming Windows" book.

Frederick2 189 Posting Whiz

Alright, so the first sends a request for the windows to be repainted whenever the width/height is edited by the user.

No, you've got the timing entirely wrong. Filling out the .style field of a WNDCLASSEX structure only occurs one time and that happens long before (in computer miliseconds) a window is created or becomes visible.

In contrast, an UpdateWindow() call can be made countless times during the execution of a running program. You need to grasp the concept of update regions possibly to fully understand this. A window can accumulate invalid regions without Windows automatically repainting it. To force an immediate WM_PAINT UpdateWindow can be used.

As I mentioned, you need to study a real solid three dimensional book with weight & mass to grasp all this.

Frederick2 189 Posting Whiz

These three items you mention refer to three distinct stages in the creation of a window using the low level Windows Api (the best way to program Windows in my opinion).

Before you can create a window you fill out all the fields of a WNDCLASSEX structure. This...

WindowClass.style = CS_HREDRAW | CS_VREDRAW;

pertains to the setting of one of the many fields (10 or so). It tells the operating system that when a window of the class szClassName is instantiated, and any change occurs to the window, the whole window should be redrawn (Windows will send a WM_PAINT message).

Note that the filling out of all the fields of a WNDCLASSEX structure is done before any windows of the class specified by the sz.ClassName field can be created/instantiated. In that sence, it represents the 1st step.

Once all the fields of the WNDCLASS striucture are filled out, one uses the RegisterClassEx() Api function to register the class with windows. the .szClassName field is of critical importance here. Let me digress for a moment.

Lets say I want to create an edit control (text box) with somewhat different characteristics than the standard/stock text box included with Windows. If I want to do that I create my own Window Class and fill out a WNDCLASSEX structure and specify the name of my new class/control through the .szClassName field. Lets say I call mine "MyEdit" . This would distinguish my edit control class from Windows own …

Frederick2 189 Posting Whiz

Went through & changed all the SQLCHAR to char and that removed the need for 98% of the casting. Now, only the SQL function calls need cast. Anyway, here is a C++ version tested with VC++ 6 and with quite a few explanatory comments...

/*  MkDB.c  To get this working in DevC++ create a new C project in its own directory
    such as MkDB, then copy this file into a C source code file and name it Main.c.
    Then go to the 'Project' on the main menu and select 'Project Options'.  A tabbed
    dialog box will open and select the 'Parameters' tab.  The 'Linker' list box at the
    far right has a button under it  which when clicked will display an 'Open File'
    dialog box where you will have to navigate to the 'lib' directory.  It is a multi-
    file selection dialog box and you will have to select the libodbc32.a and the
    libodbccp32.a libraries.

    Tested with MS VC++ 6 8/4/2009 compiling as C++ with .cpp extension
*/

#include "windows.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "odbcinst.h"                  //Necessary to create access database
#include "sql.h"                       //ODBC header file
#include "sqlext.h"                    //ODBC header file

typedef struct tagSQL                  //This type helps with some 'grungy' initialization work
{                                      //in setting up an ODBC environment
 char            szCnIn[512];
 char            szCnOut[512];
 short int       iBytes;
 SWORD           swStrLen;
 SQLHENV         hEnvr;
 SQLHDBC         hConn;
 unsigned int    blnConnected;
}SQL,*lpSql;

typedef struct tagDiagRec              //ODBC functions return wonderful error information
{                                      //and this type helps in setting it up.  I have
 SQLINTEGER …