Frederick2 189 Posting Whiz

Yea, I saw that about the type casting too. I fooled with it for about five minutes and didn't have time to finish it. I was thinking of wrapping that thing in classes, but just hadn't got around to it. Actually, I have a PowerBASIC GUI implementation of that where you click a button and the program creates an output window and prints everything to that window instead of a console window; but its posted in the PowerBASIC forums. Its straight Sdk code though.

Never was sure why the creators of the low level ODBC Api had to use those odd redifinitions of char.

Frederick2 189 Posting Whiz

Thanks again Ancient Dragon! It works for me now in Code::Blocks & Dev C++.

I'd have never thought of that myself. My mind just wasn't going in that direction. Funny how the extern "C" caused it to work with the MS compilers. Removing that there caused it to fail.

Frederick2 189 Posting Whiz

Hello Nihan1,

Below (if it all fits) is a C console program that uses direct ODBC function calls to create an Access Database in whatever directory you run the executable from, it then creates a table in the database, adds some data to it, then dumps the data to the console - providing output all the way. Certainly there are C++ classes to wrap all this as Ancient Dragon mentioned, but I simply do it as this code shows.

Also, an only slightly modified version of this program will do the same thing with SQL Server.

This particular program was compiled with Dev C++, but also works with VC++ 6. I imagine with Code::Blocks too. You need to add references to the ODBC libs.

/*  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.
*/
#include "windows.h"
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "odbcinst.h" …
Ancient Dragon commented: Nice program :) +36
Frederick2 189 Posting Whiz

Thanks a lot for looking at this AncientDragon! You've helped me before too!

Its getting late here so I'll have to experiment with this tomorrow morn I fear. However, this intrigued me...

...then it dawned on me that when all the methods are inlined like you have them you don't need that dll at all.

I don't quite understand. By inlining the functions they don't get exported or references put in the *.a file??? Even when __declspec(dllexport) is used? Humm.

Frederick2 189 Posting Whiz

I can't figure out for the life of me how to import a class declared, defined and implemented within a dll into a host app using any GNU build systems. The two compiler suites I have are Dev C++ and the newer Code::Blocks.

I have no problem with this using any Microsoft products that I have. The two Microsoft products I have are Visual C++ 6 and eMbedded Visual C++ 4.0.

Below is a simple test dll & host app to show my difficulty, along with Compile Log tab and Compiler Tab from Dev C++ (The CodeBlocks errors are exactly the same). The dll - dllCBox - just creates and exports a simple class to calculate the volume of a box. The host app simply tries to import the class, declare a CBox, and output its volume. Note that this is just a test case I put together to concisely show the problem. In the real situation I create a String class of my own within a dll where I create several grid custom controls. In the host that creates instances of the custom controls I also have access to my string class. This architecture is something I use to good advantage frequently, rather than implementing the same string class in the dll & the host app, which would be wasteful. Anyway, here is the example...

//Project dllCBox;  File dllMain.cpp
#include <windows.h>
#include <stdio.h>

extern "C" class __declspec(dllexport) CBox
{
 public:
 CBox(double dblLen, double dblWidth, double dblHeight) …
Frederick2 189 Posting Whiz

When a Sdk type Api program starts, one of the first (not the first, but one of the first) messages your main window will receive is the WM_CREATE message. In the message handler for that message you can create additional child windows of the main form/dialog/window such as buttons, listboxes, edit controls, etc. This is accomplished by additional calls to CreateWindowEx() where the 2nd parameter is the window class you want to create, i.e., "button", and parent parameter is the HWND of your main window. In standard 'Petzold' style Sdk code the WM_CREATE message will be processed within the main windows WndProc. However, I always create message cracker functions in my code and relagate each message's processing to handler functions. I typically create all my child window controls in a function such as...

long fnWndProc_OnCreate(....)
{
hButton=CreateWindowEx(...._;
...

return 0;
}

here's a simple example of adding a button...

#include <windows.h>
#define IDC_BUTTON   WM_USER + 1

LRESULT CALLBACK WindowProcedure(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
 HINSTANCE hIns;
 HWND hButton;
 
 switch(msg)
 {
  case WM_CREATE:
    hIns=((LPCREATESTRUCT)lParam)->hInstance;
    hButton=CreateWindow("button","Click Me",WS_CHILD|WS_VISIBLE,70,60,150,30,hwnd,(HMENU)IDC_BUTTON,hIns,0);
    break;
  case WM_COMMAND:
    MessageBox(hwnd,"You Clicked The Button","Message",MB_OK);
    break;
  case WM_KEYDOWN:
    if(wParam==VK_DELETE)
       MessageBox(hwnd,"You Clicked The Delete Key!","Delete!",MB_OK);
    break;
  case WM_SYSKEYDOWN:
    if((lParam&0x20000000)&&wParam==VK_DELETE)
        MessageBox(hwnd,"Alt + Delete Key!","Delete!",MB_OK);
    break;
  case WM_DESTROY:
    PostQuitMessage (0);
    break;
  default:
    return DefWindowProc(hwnd,msg,wParam,lParam);
 }

 return 0;
}

int __stdcall WinMain(HINSTANCE hIns,HINSTANCE hPrevIns,LPSTR lpszArgument,int iShow)

{
 char szClassName[]="WindowsApp";
 WNDCLASSEX wincl; 
 MSG messages;
 HWND hWnd; 

 wincl.hInstance=hIns;
 wincl.lpszClassName=szClassName;
 wincl.lpfnWndProc=WindowProcedure;
 wincl.style=CS_DBLCLKS;
 wincl.cbSize=sizeof (WNDCLASSEX);
 wincl.hIcon=LoadIcon(NULL,IDI_APPLICATION);
 wincl.hIconSm=LoadIcon(NULL, IDI_APPLICATION);
 wincl.hCursor=LoadCursor(NULL,IDC_ARROW);
 wincl.lpszMenuName=NULL;
 wincl.cbClsExtra=0;
 wincl.cbWndExtra=0;
 wincl.hbrBackground=(HBRUSH)COLOR_BACKGROUND; …
Frederick2 189 Posting Whiz

Or just get used to using TEXT() macros all over the place, and stop worrying about what each revision of the IDE defaults to for character encoding.

UNICODE isn't going away any time soon, so you're going to have to learn to deal with it.

Yes, you're right Salem! But its hard! Last year I spent about six months working on a large Win CE program, and at some point I would like to be able to get that working on the Windows desktop. I'd have been a lot further ahead probably had I just caved in to the whole text macro thing (TEXT(""), and so forth), but, the stuff very much affronts my long developed coding style sensibilities.

C++ probably had no alternative in the matter, being as its the type of language it is. So acceptance is the only alternative if one is going to use C++. Other language products of course have other alternatives. Thanks again all for the feedback.

Frederick2 189 Posting Whiz

Thanks ArkM. I'll give that a try. I had snooped around in there looking for something relating to unicode settings, but as you know, its considerably different from my old VC 6 (actually, now that I've seen it, I know where the CodeBlocks look came from......).

Frederick2 189 Posting Whiz

Just downloaded VC++ 8.0 Express and tried to run a simple sdk style program to see what happens. I've been using Dev C++, CodeBlocks, and MS VC++ 6. I've been advised to get up to date. Anyway, to get the program to run I had to change all the Api calls with string parameters to 'A' versions. If my memory serves me correct with my other compilers there were #defines of UNICODE and/or _UNICODE that controlled whether 'A' or 'W' versions of the declares were compiled. When I saw what was happening I tried to #undef UNICODE and _UNICODE, but that didn't result in any positive outcome.

The other issue I had was with the .lpfnWndProc member of WNDCLASSEX. It appears WNDPROC must be redefined somewheres because intellisence was telling me it wanted a LPCWSTR instead of LPCTSTR or whatever it was before (believe that's right, and would reduce to LPCSTR if UNICODE wasn't defined). So to get that to work I had to put a 'L' in front of the string name of the window procedure.

Is there a way to just get it to default to the 'A' versions of things? I do a lot of Windows CE programming and there I've had to more or less make peace with the way things are so I use wchar_t instead of char and preface all my literals with 'L' as that seems like the easiest and cleanest alternative and spares me from those aweful TEXT and _T …

Frederick2 189 Posting Whiz

I prettied it up a bit.

#include <windows.h>
#define IDC_TEXTBOX   1500
#define IDC_BUTTON    1505


LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 HWND hCtrl;
  
 switch (message)
 {
  case WM_CREATE:
    hCtrl=CreateWindowEx(0,"button","button #1",WS_CHILD | WS_VISIBLE,67,15,100,25,hwnd,(HMENU)IDC_BUTTON,((LPCREATESTRUCT)lParam)->hInstance,0);
    hCtrl=CreateWindowEx(0,"edit",0,WS_CHILD | WS_VISIBLE,15,60,210,25,hwnd,(HMENU)IDC_TEXTBOX,((LPCREATESTRUCT)lParam)->hInstance,0);
    return 0;
  case WM_COMMAND:
    switch (LOWORD(wParam))
    {
     case IDC_BUTTON:
       SetWindowText(GetDlgItem(hwnd,IDC_TEXTBOX),"Text In A Text Box");
       break;
     default:
       break;
    }  
    return 0;
  case WM_CLOSE:
    PostQuitMessage(0);
    return 0;
 }

 return DefWindowProc(hwnd, message, wParam, lParam);
}


int __stdcall WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int iCmdShow)
{
 WNDCLASSEX wincl;
 MSG messages;
 HWND hMain;

 wincl.hInstance = hInstance;
 wincl.lpszClassName = "Form3";
 wincl.lpfnWndProc = WindowProcedure;
 wincl.style = CS_HREDRAW | CS_VREDRAW;
 wincl.cbSize = sizeof(WNDCLASSEX);
 wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
 wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
 wincl.lpszMenuName = NULL;
 wincl.cbClsExtra = 0;
 wincl.cbWndExtra = 0;
 wincl.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
 RegisterClassEx(&wincl);       //Register Main Window Class
 hMain=CreateWindow("Form3","Caption = Form3",WS_OVERLAPPEDWINDOW,0x8000,0x8000,250,200,HWND_DESKTOP,0,hInstance,0);
 ShowWindow(hMain, iCmdShow);
 while(GetMessage(&messages, NULL, 0, 0))
 {
  TranslateMessage(&messages);
  DispatchMessage(&messages);
 }

 return messages.wParam;
}

That is SetWindowText() if that's all you want to do. You could also write your own keypress code in a RegisterClassEx window. But then you would have to duplicate all the functionality of the predefined edit control.

Frederick2 189 Posting Whiz

Here's an old program I dug up that puts text in a edit control when you click the button. Boy, its horrible code, but runs.

#include <windows.h>
#include <stdio.h>
#include <string.h>
HWND hMainWnd;
HINSTANCE ghIns;
UINT iStyle=WS_CHILD|WS_VISIBLE;
HWND hTxtBox;
char szText[50];

LRESULT CALLBACK WindowProcedure(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
 static HWND hButton;
  
 switch (message)
 {
  case WM_CREATE:
    strcpy(szText,"Fred");   
    hButton=CreateWindow("button","button #1",iStyle,67,15,100,25,hwnd,(HMENU)(1),((LPCREATESTRUCT)lParam)->hInstance,0);
    hTxtBox=CreateWindow("edit",0,iStyle,15,60,210,25,hwnd,(HMENU)(2),((LPCREATESTRUCT)lParam)->hInstance,0);
    return 0;
  case WM_COMMAND:
    switch (LOWORD(wParam))
    {
     case 1:
       SetWindowText(hTxtBox,szText);
       break;
     default:
       break;
    }  
    return 0;
  case WM_CLOSE:
    PostQuitMessage(0);
    return 0;
 }

 return DefWindowProc(hwnd, message, wParam, lParam);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpszArgument, int iCmdShow)
{
 MSG messages;
 WNDCLASSEX wincl;
 
 ghIns=hInstance;
 wincl.hInstance = hInstance;
 wincl.lpszClassName = "Form1";
 wincl.lpfnWndProc = WindowProcedure;
 wincl.style = CS_HREDRAW | CS_VREDRAW;
 wincl.cbSize = sizeof(WNDCLASSEX);
 wincl.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 wincl.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
 wincl.hCursor = LoadCursor(NULL, IDC_ARROW);
 wincl.lpszMenuName = NULL;
 wincl.cbClsExtra = 0;
 wincl.cbWndExtra = 0;
 wincl.hbrBackground = (HBRUSH) GetStockObject(LTGRAY_BRUSH);
 RegisterClassEx(&wincl);       //Register Main Window Class
 hMainWnd=CreateWindow("Form1","Caption = Form1",1040384,0x8000,0x8000,250,200,HWND_DESKTOP,0,hInstance,0);
 ShowWindow(hMainWnd, iCmdShow);
 while(GetMessage(&messages, NULL, 0, 0))
 {
  TranslateMessage(&messages);
  DispatchMessage(&messages);
 }

 return messages.wParam;
}
Frederick2 189 Posting Whiz

[I'm just wondering how they work...]

Well, that's not exactly something that can be explained in 'just' five minutes - you know, kind of out of like say - 'mild curiousity'.

How GUI aplications work was the culmination of the lifetimes of study/theorizing on the part of computer scientists on the cutting edge of their discipline back in the late 1970's. Their work came to fruition at the Xerox Palo Alto labs in the late seventies and early eighties. Apple picked up on it first. Then Bill Gates and Microsoft.

Highly renowned writer Charles Petzold introduced Windows GUI programming to C programmers back in the late 1980s with his famous 'Programming Windows' books. That is how most Windows developers learned GUI programming. Petzold's books were aimed at professional C programmers, that is, people not just learning to program, but rather folks who were already very competant professional programers who were masters of the C programming language. The nature of the subject was so difficult & complicated that Petzold stated it would take such a aspiring professional C programmer six months of hard study to become somewhat competant at Windows programming.

The situation with Linux/Unix GUI development is the same - just different names involved - mostly from MIT I believe.

So, if you are just mildly curious, I'd just forget it.

Frederick2 189 Posting Whiz

If my memory serves me the Linux package you need to install to program using xlib is xorg.dev.

For Gtk its libgtk or something like that. Again, check the Linux forums. I personally only dabble in Linux development, as I'm mainly an sdk style api coder. I'd like to do more with Linux, but have a hard time finding the time. But anyway, here are a couple more gui Linux programs, 1st a HelloWorld using xlib, then a gtk+ program that puts a button in a window...

/*
   gcc HelloWorld.c  -o HelloWorld  -L/usr/X11R6/lib  -lX11
*/

#include <X11/Xlib.h>
#include <stdlib.h>
#include <string.h>

int main(int argc, char* argv[])
{
 Display* display;
 Atom ProtocolAtom,KillAtom;
 int blackColor,whiteColor,iScreen;
 Window hRoot,hMain;
 char* pDisp;
 XEvent e;  

 pDisp=getenv("DISPLAY");
 display=XOpenDisplay(pDisp);
 if(!display)
    return 1;
 hRoot=DefaultRootWindow(display);
 blackColor=BlackPixel(display,DefaultScreen(display));
 whiteColor=WhitePixel(display,DefaultScreen(display));
 iScreen=DefaultScreen(display);
 hMain=XCreateSimpleWindow(display,hRoot,200,200,350,300,0,blackColor,whiteColor);
 ProtocolAtom=XInternAtom(display,"WM_PROTOCOLS",False);
 KillAtom=XInternAtom(display,"WM_DELETE_WINDOW",False);
 XSetWMProtocols(display,hMain,&KillAtom,1);
 XSelectInput(display,hRoot,SubstructureNotifyMask);
 XSelectInput(display,hMain,ExposureMask);
 XMapWindow(display,hMain);
 while(1)
 {
  XNextEvent(display,&e);
  switch(e.type)
  {
   case Expose:
     XDrawString(display,hMain,DefaultGC(display,iScreen),130,100,"Hello, World!",strlen("Hello, World!"));
     break;
   case ClientMessage:
     if(e.xclient.message_type==ProtocolAtom && e.xclient.data.l[0]==KillAtom)
     {
        XCloseDisplay(display);
        exit(0);
     }
     break;
   default:
     break;
  }
 }

 return 0;
}

The above program, although short, has some real, real complicated stuff in it involving tapping into the low level x messaging protacols to catch a click of the [x] button to close the window. In any demonstration programs you will find any where on the net programs will be ended by a keystroke. It took me weeks to figure this out.

Here's the gtk program...

/*
fred@CodeWarrior:~$ cd code/gtk
fred@CodeWarrior:~/code/gtk$ gcc buttons.c -o buttons `pkg-config --cflags gtk+-2.0` `pkg-config --libs gtk+-2.0`
fred@CodeWarrior:~/code/gtk$ ./buttons
fred@CodeWarrior:~/code/gtk$ …
Frederick2 189 Posting Whiz

To get an x windows gui program running in Ubuntu 8.1 or any other Linux/Unix you need to have the xlib development libraries installed. You can search the UBuntu forums for how to do that. Here is a command line (Terminal) description of getting an xlib program running. 1st here is a program that produces a blank window that can be correctly closed with the [x] button in the title bar...

/* 
   Form1.c
   Compiler        = gcc
   Program Name    = Form1.c
   Executble Name  = Form1
   Link Path       = /usr/X11R6/lib
   Link            = X11
 
   Command Line:   gcc Form1.c  -o Form1  -L/usr/X11R6/lib  -lX11  
*/

#include <X11/Xlib.h>

int main(int argc, char* argv[])
{
 char* display_name;
 Display* display;
 int screen_num;
 Window hWnd;

 display_name=(char*)getenv("DISPLAY");
 display=XOpenDisplay(display_name);
 if(!display)
    return (1);
 screen_num=DefaultScreen(display);
 hWnd=
 XCreateSimpleWindow
 (
    display,                         //pointer to Display struct, kind of GDI object?
    RootWindow(display,screen_num),  //parent of hWnd
    50, 50, 500, 450,                //x, y, width, height
    2,                               //window border width
    BlackPixel(display,screen_num),  //foreground 'brush'
    WhitePixel(display,screen_num)   //background 'brush'
 );
 XMapWindow(display,hWnd);           //ShowWindow(hWnd);
 XSync(display,False);               //UpdateWindow()  ???
 sleep(30);                          //prevent from ending???
 XCloseDisplay(display);             //Shut down connection to X

 return (0);
}

The command line compiling info is at top. It will produce a program named Form1. To run it put a shortcut to it on your desktop or do this in the Terminal...

fred@CodeWarrior:~$ cd code/xlib
fred@CodeWarrior:~/code/xlib$ gcc Form1.c -o Form1 -L/usr/X11R6/lib -lX11
fred@CodeWarrior:~/code/xlib$ ./Form1

My name is fred and my computer's name is CodeWarrior. I had the source code in a subdirectory of my /home folder /code/xlib/Form1.c. To run the …

Frederick2 189 Posting Whiz

Linux it is then! If you would like I'll post some XLib & GTK programs that show what it looks like to get A GUI window up and running. But to understand it you really need a decent knowledge of C / C++. It gives me a good deal of satisfaction that C is taken pretty seriously in Linux development. The Linux toolkit (application framework) I use is GTK. I'd look into installing that. Here is a link to a good GTK forum...

http://www.gtkforums.com/

Not sure what is here at daniweb in terms of Linux C++ development. Perhaps there is a forum here on that too.

Frederick2 189 Posting Whiz

What platform are you working with Orwell84? Windows, Linux, ??? If Windows, then you either need to learn the Windows Api, or adopt some Windows Application Framework such as MFC, .NET, etc. For myself, I just about strictly use the Windows Api directly for Windows programming.

For Linux I dabble in lots of different stuff GTK, xlib, motif, etc.

There's lots of choices. It seems just about everybody and all books start out with console mode programs because a beginner has to learn about variable types, decision structures, etc., first. Once you get that stuff down you can think about learning GUI programming. That's a C++ prospective.

If you start with vb.net or c# some of the books start pretty much directly with GUI coding. Hope this info helps.

Frederick2 189 Posting Whiz

Hi Again ArkM!

I've basically moved on. I was thinking of seeing what would happen using the Win32 Console output functions; but there too it would be necessary to use something or other from the printf family of functions such as sprintf or whatever to write a variable's output to a buffer for console output with WriteConsole().

In terms of the missing () from volume() you mentioned above; that had no effect as I had tried it too. Believe it or not, what would solve the problem was eliminating that last variable from the printf function and just ending the format string with a \t instead of \n and outputing the this->volume() with a seperate printf. The output of course (the correct one) would be the same. Observations such as this led me to believe my code was OK and the problem was a VC++ thing.

I'm actually working on templates, and that's where I encountered the problem. Since I'm not sure of what I'm doing there yet I figured I was making some sort of template related mistake, but couldn't find it. That's when I created the code I posted without any templates and the problem still couldn't be eliminated (with VC++). I changed the variable declarations to ints and that eliminated the problem. Below is the same code with templates and it works fine.

I'm using VC++ 6 because I want to learn ATL and I don't have a newer version of it. I …

Frederick2 189 Posting Whiz

Hi ArkM!

 Here's the result from couts (took me a minute or two to think how to do it):

2       3       1       6
2.2     1       0.5     1.1
0.2     3.5     2       1.4
0.3     3       3       2.7


2       3       1       6
2.2     1       0.5     1.1
0.2     3.5     2       1.4
0.3     3       3       2.7
Press any key to continue

That is correct output.

I've lots of versions of that program - been fooling with it all afternoon in disbelief of what I'm seeing. The first output I presented was typical. Never thought to try couts as I never use that library. I actually hate it.

I'm really beginning to think its a VC++ bug. I'll play with it somemore but can't imagine what's going on. I'm actually not a beginner - however I do make stupid mistakes more frequently than I'd like - and perhaps there's one in my code. Its just about too much to believe there is a bug in VC++ - its too good a compiler.

Frederick2 189 Posting Whiz

Have you ever had a problem where you are completely dumbfounded? Staring at the output of a program and saying this is impossible? Sort of like…

int a =5;
printf(“a=%d\n”,a);

Output:
A=6

Well, I’d appreciate if someone would take a look at this simple program below which creates a class Cbox that has just length, width, and height private double members, and a volume function to return the volume. Then I create an array of Cboxes named CArray. Oh, the Cbox class has a display() member function to output the three sides and the volume. That is important because that is where the screw up is occurring, i.e., when I try to call the display() function either on an individual Cbox object, or in a loop to dump all Cboxes from the array. Just to give you an idea of the kind of corruption I’m seeing before I show you the program, here is a little output:

m_Length = 2.000000       m_Width = 3.000000      m_Height = 1.000000     volume() = 2181932029977806200
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000
m_Length = 2.200000       m_Width = 1.000000      m_Height = 0.500000     volume() = 1200062616487793500
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.000
m_Length = 0.200000       m_Width = 3.500000      m_Height = 2.000000     volume() = 4363864059955613000
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0000
m_Length = 0.300000       m_Width = 3.000000      m_Height = 3.000000     volume() = 9818694133995429100
00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000.0000
[/CODE=C++]

I think you get the idea.

I’ve run this program on two different computers using three different compilers/development environments, i.e., Microsoft Visual C++ 6.0, Dev C++, and the new CodeBlocks. …
Frederick2 189 Posting Whiz

if its not in a class look at memset(). That will set any range of bytes (if they are in your process) to whatever you want. For example, if you've got a thousand doubles and you want that memory all set to nulls, you would call the function with the starting address and the number of bytes you want filled - here 8000.

Frederick2 189 Posting Whiz

Thanks Narue! That did it. I really appreciate your taking the time to figure out my rather longish post. Now I have a few working examples of templates in use that I can study. I discovered I didn't understand the syntax for passing template classes as reference parameters when I attempted to do it.

Frederick2 189 Posting Whiz

I’m trying to learn how to use C++ templates, and I thought I was grasping it all ok until I decided to try to pass a template defined object variable as a function parameter. Having all kinds of troubles with that.

I’m using a typical example of a parameterizd array class. The members of the array are client objects with a name, gender, and age, i.e.,

Fred   m    56
Sue    f    46
Mary   f    21

Etc.

This class is CClient

class CClient          //CClients
{
 public:
 CClient();
 ~CClient();
 void SetName(CString s);
 void SetGender(char gender);
 void SetAge(int iAge);
 void input();
 void display(unsigned int ctr) const;

 private:
 CString m_Name;
 char    m_Sex;
 int     m_Age;
};

My template is an array that should be able to hold some number of these, i.e.,

template<class Tpl> class CArray
{
 public:
 CArray();
 ~CArray();
 
 bool AddNew(Tpl& pObj);        //adds a new Tpl to Carray object
 unsigned int get_size() const; //returns actual number in CArray
 void dump();                   //dumps objects to console
 
 private:
 unsigned int m_New;            //marks last/new object position
 Tpl x[MAX_SIZE];               //array of whatever
};

Actually, I have this part working. If you take a look at the CClient class above you’ll see an input() member function declaration. I had implemented that with a scanf() to get series of names, genders, and ages from the keyboard. I was calling that from main(). That got pretty tiresome entering all that data by hand repeatedly just to test the workings of the classes and so forth, so I …

Frederick2 189 Posting Whiz

If you are going to be doing much work with console screens (DOS screens some people refer to them, but that isn't right) you need to become familiar with the Win32console functions.

Frederick2 189 Posting Whiz

Thanks for the tip AncientDragon. Believe it or not I was doing command line compiling with Notepad, but I took your advice and created a VC++ 6 project with the source. When I did the show definition thing it took me to ocidl.h as I described above where it is defined as...

EXTERN_C const IID IID_IConnectionPoint;

If a c++ file EXTERN_C resolves to extern "C" I believe. But that still doesn't actually define it if its prefixed with any form of the C keyword 'extern' does it?

I've got several COM books already. What I need are more brains!

Frederick2 189 Posting Whiz

Been studying COM for some time now and for the life of me I can't find out how some of these standard interfaces such as IID_IConnectionPointContainer, IID_IConnectionPoint, etc., are actually defined. I can pass these IIDs in QueryInterface() calls and successfully retrieve pointers to them, so they must be actually defined somewhere, right?

In ocidl.h can be found things like this...

typedef IConnectionPoint __RPC_FAR *PCONNECTIONPOINT;
typedef IConnectionPoint __RPC_FAR *LPCONNECTIONPOINT;
EXTERN_C const IID IID_IConnectionPoint;

#if defined(__cplusplus) && !defined(CINTERFACE)
MIDL_INTERFACE("B196B286-BAB4-101A-B69C-00AA00341D07")
IConnectionPoint : public IUnknown
{
 public:
 virtual HRESULT STDMETHODCALLTYPE GetConnectionInterface(IID __RPC_FAR *pIID)=0;
 virtual HRESULT STDMETHODCALLTYPE GetConnectionPointContainer(IConnectionPointContainer __RPC_FAR *__RPC_FAR *ppCPC)=0;
 virtual HRESULT STDMETHODCALLTYPE Advise(IUnknown __RPC_FAR *pUnkSink,DWORD __RPC_FAR *pdwCookie)=0;
 virtual HRESULT STDMETHODCALLTYPE Unadvise(DWORD dwCookie)=0;
 virtual HRESULT STDMETHODCALLTYPE EnumConnections(IEnumConnections __RPC_FAR *__RPC_FAR *ppEnum)=0;
};
#else 	/* C style interface */
typedef struct IConnectionPointVtbl
{
 BEGIN_INTERFACE
 HRESULT (STDMETHODCALLTYPE __RPC_FAR* QueryInterface)(IConnectionPoint __RPC_FAR* This,REFIID riid,void __RPC_FAR *__RPC_FAR *ppvObject);
 ULONG (STDMETHODCALLTYPE __RPC_FAR* AddRef)(IConnectionPoint __RPC_FAR* This);
 ULONG (STDMETHODCALLTYPE __RPC_FAR* Release)(IConnectionPoint __RPC_FAR* This);
 HRESULT (STDMETHODCALLTYPE __RPC_FAR* GetConnectionInterface)(IConnectionPoint __RPC_FAR* This, IID __RPC_FAR* pIID);
 HRESULT (STDMETHODCALLTYPE __RPC_FAR* GetConnectionPointContainer)(IConnectionPoint __RPC_FAR* This,IConnectionPointContainer __RPC_FAR* __RPC_FAR* ppCPC);
 HRESULT (STDMETHODCALLTYPE __RPC_FAR* Advise)(IConnectionPoint __RPC_FAR* This, IUnknown __RPC_FAR* pUnkSink, DWORD __RPC_FAR* pdwCookie);
 HRESULT (STDMETHODCALLTYPE __RPC_FAR* Unadvise)(IConnectionPoint __RPC_FAR* This, DWORD dwCookie);
 HRESULT (STDMETHODCALLTYPE __RPC_FAR* EnumConnections)(IConnectionPoint __RPC_FAR* This, IEnumConnections __RPC_FAR* __RPC_FAR* ppEnum);
 END_INTERFACE
}IConnectionPointVtbl;

...which includes this line...

EXTERN_C const IID IID_IConnectionPoint;

But of course that has an EXTERN modifier in front of it. Does that MIDL_INTERFACE macro somehow cause it to be defined. Quite honestly, I'm not sure just what that does. I've looked it up but still …

Frederick2 189 Posting Whiz

Well! The solution is obvious! If it wants a this pointer, then pass it one (to balance the stack)! This runs perfect in all three environments and no crashes!

#include <stdio.h> 

struct IX
{ 
 virtual void __stdcall Fx1()=0; 
 virtual void __stdcall Fx2()=0;
};  


struct IY
{ 
 virtual void __stdcall Fy1()=0; 
 virtual void __stdcall Fy2()=0;
};  


class CA : public IX, public IY
{ 
 virtual void __stdcall Fx1(){printf("Called Fx1()\n");}  
 virtual void __stdcall Fx2(){printf("Called Fx2()\n");}  
 virtual void __stdcall Fy1(){printf("Called Fy1()\n");}  
 virtual void __stdcall Fy2(){printf("Called Fy2()\n");}     
};

int main(void)
{ 
 void (__stdcall*pFn)(int);
 unsigned int* ptrVTbl=0;    
 unsigned int* VTable=0;      
 unsigned int i=0,j=0;        
 CA* pCA=0;                    
 
 printf("sizeof(CA) = %u\n\n", sizeof(CA)); 
 pCA=new CA; 
 ptrVTbl=(unsigned int*)pCA; 
 printf("i\t&ptrVTbl[]\t&VTable[]\tVTable[]\tpFn()\n"); 
 printf("====================================================================\n"); 
 for(i=0;i<2;i++) 
 {     
     VTable=(unsigned int*)ptrVTbl[i];     
     for(j=0;j<2;j++)     
     {
         printf
         (
          "%u\t%u\t\t%u\t\t%u\t\t",  //format specifiers
          i,                         //iterator
          &ptrVTbl[i],               //bytes 0-3 offset from pCA for i=0 and 4-7 when i=1 
          &VTable[j],                //address of function pointer held in VTable
          VTable[j]                  //value of function pointer in Vtable, i.e., address of function
         );
         pFn=(void(__stdcall*)(int))VTable[j]; //call function through function pointer
         pFn((int)pCA); //give it something to pop, even though its not used!                
     }
 } 
 printf("\n"); 
 getchar();
   
 return 0;
}
dougy83 commented: Clever! +2
Frederick2 189 Posting Whiz

I really appreciate your looking at this Dougy83. It most definitely looks like there is a problem - as I thought. With my level of expertise I just couldn't take it any further than I did. I've printed out those links and will study them. It looks to me like I need to learn how to use a stepping debugger and understand asm code (so far I've managed without it).

My whole reason for doing this was simply to learn a few of the details of how COM objects are laid out in memory. Somehow just looking at the pictures and drawings in books didn't quite satisfy me. I needed to get my hands dirty I guess. Then, just when I thought I had it all figurred out, I kept getting these strange problems that to me anyway had all the signs of some kind of memory corruption, i.e., GPFs in MS VC++, worked perfect in Dev-CPP, and partially corrupted memory address output in Code::Blocks gcc but no GPFs. I gather from your conclusions that there are no easy 'one liner' type fixes.

I'm also wondering at this point how this affects access to COM objects (which use this memory layout) from other languages. The main language I use for PC programming is PowerBASIC (www.powerbasic.com). I mostly use VC++ for WinCE devices. From what I've read from your links and comments it sounds like that will depend on how that other language handles pushing/poping registers and …

Frederick2 189 Posting Whiz

Well, nobody seems to be replying to my thread in terms of telling me what my error is, and I took that as being ignored. However, in the meantime I just tried a neat piece of code posted several weeks ago by vijayan121 at...

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

and that crashes too after providing correct output - just like mine. I'm now beginning to wander if there isn't something wrong with the VC 6 compiler that is causing this - not my (our) code? I can't expect for someone to reveal a bug to me if there isn't any I guess.

Frederick2 189 Posting Whiz

I have not been able to obtain an answer to this question anywhere (including here) so I’ll ask it again. I can understand that folks don’t want to wade through hundreds of lines of code looking for someone else’s bug, so I’ve worked very hard to produce the very smallest possible program I can to illustrate my difficulty. Below is a working program using all __cdecl function calling – and I know I could have eliminated the __cdecl as that is the default. However, I put it in to emphasize the fact that in the next program it will be replaced with __stdcall. Here is the program and the output is directly following…

#include <stdio.h>

struct IX
{
 virtual void __cdecl Fx1()=0;
 virtual void __cdecl Fx2()=0;
};


struct IY
{
 virtual void __cdecl Fy1()=0;
 virtual void __cdecl Fy2()=0;
};


class CA : public IX, public IY
{
 virtual void __cdecl Fx1(){printf("Called Fx1()\n");} 
 virtual void __cdecl Fx2(){printf("Called Fx2()\n");} 
 virtual void __cdecl Fy1(){printf("Called Fy1()\n");} 
 virtual void __cdecl Fy2(){printf("Called Fy2()\n");}     
};


int main(void)
{
 void (__cdecl*pFn)(void);    //function pointer to void function that returns void
 unsigned int* ptrVTbl=0;     //pointer to Vtable.  There are two,e.g., an IX & IY
 unsigned int* VTable=0;      //Virtual Function Table for IX and IY, respectively
 unsigned int i=0,j=0;        //iterator variables
 CA* pCA=0;                   //ptr to class CA

 printf("sizeof(CA) = %u\n\n", sizeof(CA));
 pCA=new CA;
 ptrVTbl=(unsigned int*)pCA;
 printf("i\t&ptrVTbl[]\t&VTable[]\tVTable[]\tpFn()\n");
 printf("====================================================================\n");
 for(i=0;i<2;i++)
 {
     VTable=(unsigned int*)ptrVTbl[i];
     for(j=0;j<2;j++)
     {   
         printf
         (
          "%u\t%u\t\t%u\t\t%u\t\t",  //format specifiers
          i,                         //iterator
          &ptrVTbl[i],               //bytes 0-3 offset from pCA for i=0 and 4-7 …
Frederick2 189 Posting Whiz

Thanks for the links ArtM. I've saved them and will definitely print out the one. In terms of the Stanley Lippman book "The C++ Object Model", I've had that for some time. Unfortunately, I have not yet attained that exalted state of C++ competance where its reading is in any way benificial to me. What would be especially benificial to me in my present mentally depaupeurate state would be knowledge of what a process return value of 0xC0000005 means. For you see, that is what I am getting from the new Code::Blocks created program I am running. My Microsoft Visual C++ program builds and runs perfectly, but with any GNU compiler product I get various problems, and I'd like to know what sort of havoc I'm causing. Below is the output from the Code::Blocks compiled program. It runs and produces perfect output until it closes out with a crash...

sizeof(CA)            = 8        : An IX VTBL Ptr And A IY VTBL Ptr
pCA                   = 3146576  : Ptr To IX VTBL
*(int*)(&pCA)         = 3146576  : With Just More Convoluted Notation.
*(int*)*(int*)(&pCA)  = 4219068  : Ptr to Ptr For IX::QueryInterface()
pVTbl                 = 3146576

&pVTbl[i]       &VTbl[j]        pFn=VTbl[j]     pFn()
=========================================================================
3146576         4219068         4198656         Called QueryInterface()
3146576         4219072         4198688         Called AddRef()
3146576         4219076         4198720         Called Release()
3146576         4219080         4198752         Called Fx1()
3146576         4219084         4198768         Called Fx2()

3146580         4219048         4198816         Called QueryInterface()
3146580         4219052         4198832         Called AddRef()
3146580         4219056         4198848         Called Release()
3146580         4219060         4198784         Called Fy1()
3146580         4219064         4198800         Called Fy2()

Process returned -1073741819 …
Frederick2 189 Posting Whiz

I am trying to understand COM memory layout and using C++ classes just confuses me. In general I understand what is going on with the double indirection of function pointers but as so often is the case in programming one must understand the ugly details – not just the generalities. So I thought I would create a very simple example and attempt to call a few functions contained in a couple interfaces without using typical C++ object call syntax but just using C style function pointers and addresses I could dig/pry/coax out of a C++ class. I’ve been largely successful in this endeavor I think but I am having some difficulties that I can’t explain. I would certainly appreciate someone’s looking at this who is knowledgable in these matters (and who has perhaps waded through this stuff him/herself!). For others just learning COM there may be some merit in trying to follow what I am doing here.

Here is what I’ve done. I created two interfaces IX and IY that each inherit from Iunknown and each contain just two functions, e.g., Fx1(), Fx2(), Fy1(), and Fy2(). They are pure virtual functions within these two interfaces and are implemented in class CA where they are publically inherited. Class CA contains nothing else to complicate matters. The implementation of these functions in class CA just outputs a message that they were called. Here is the very simple construct…

interface IX : IUnknown              //will cause inheritance of
{                                    //QueryInterface(),AddRef(),
 virtual void …
Frederick2 189 Posting Whiz

An oldish book like that can probably be gotten for little more than postage used, but if I had to I'd spend a couple dollars more if necessary to make sure I got one with the CD in it. Some of the programs are long enough that it would be fairly punishing to type them in by hand.

Frederick2 189 Posting Whiz

Narue's advice is good. That was Petzold's last book on the Window's Api (he now writes about .NET and other technology topics), and he is considered quite the expert on it - especially in graphics. The Windows Api doesn't really change all that much.

Another book on the Api that some prefer is the one by Newcomen (sp? Newcomb? and Rector), but I prefer Petzold. Its how I learned. Class frameworks come and go, but the Api is always there.

edited

Its Newcomer and Rector

http://www.amazon.com/Win32-Programming-Addison-Wesley-Advanced-Windows/dp/0201634929/ref=pd_sbs_b_njs_3

but I prefer Petzold!

Frederick2 189 Posting Whiz

Thanks ArkM. That did it! The 'Brutal Force Method' suits my coding style anyhow!

Frederick2 189 Posting Whiz

Just decided to try the new Code::Blocks IDE on an old ODBC program of mine that I had always compiled as a C program. I decided to redo it as a C++ program and immediately hit a nasty problem that I never ran into in C. It involves a Typedef of char from char* to SQLCHAR*. The below example very concisely shows the problem. I can use strcpy to copy a literal char array to a char*, but not to a SQLCHAR*. This has worked flawlessly for me for years in C. No errors, no warnings, runs perfectly, etc. I was so amazed I tried it with Dev C++ but with the same result. Can anyone tell me what's wrong or how to fix it?

#include <windows.h>
#include <stdio.h>
#include <string.h>
#include "odbcinst.h"
#include "sql.h"        //ODBC header file
#include "sqlext.h"    //ODBC header file

int main()
{
 char szBuffer[64];
 SQLCHAR szString[64];

 strcpy(szBuffer,"Any Old String");
 printf("szBuffer = %s\n",szBuffer);
 strcpy(szString,"Let's Try This!");

 return 0;
}

/*
COMPILER OUTPUT

Main.cpp: In function `int main()':
Main.cpp:15: error: invalid conversion from `SQLCHAR*' to `char*'
Main.cpp:15: error:   initializing argument 1 of `char* strcpy(char*, const char*)'
make.exe: *** [Main.o] Error 1
Execution terminated
*/
Frederick2 189 Posting Whiz

I use two different compilers/development environments, i.e., Microsoft's Visual C++ 6.0 and Dev C++, the latter of which is a free and relatively small download of about 10 MB. For just starting out I'd highly recommend Dev C++ as a development environment. You can compile console or GUI Windows programs with either. Here is a link to download Dev C++/Bloodshed...

http://www.bloodshed.net

Of course, Microsoft is and has been for some time giving away various free compilers/development tools, but I personally tend to shy away from these as the download size and volume of documentation is beyond what I'm prepared to handle.

Frederick2 189 Posting Whiz

I dug up this. Try a bunch of different keys. It prints a message for quite a lot of them. I didn't test it with Dev C++, cuz it appears I wrote it with MS Visual C++ 6.0. If it doesn't work I'll see what's wrong with it. I believe you end the program by either hitting [ESCAPE] or x'ing out.

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

void cls( HANDLE hConsole )
{
 COORD coordScreen = {0,0};
 DWORD cCharsWritten;
 CONSOLE_SCREEN_BUFFER_INFO csbi;
 DWORD dwConSize;
 
 GetConsoleScreenBufferInfo(hConsole, &csbi);
 dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
 FillConsoleOutputCharacter(hConsole,(TCHAR)' ',
 dwConSize,coordScreen,&cCharsWritten);
 GetConsoleScreenBufferInfo( hConsole, &csbi);
 FillConsoleOutputAttribute( hConsole, csbi.wAttributes,
 dwConSize, coordScreen, &cCharsWritten );
 SetConsoleCursorPosition( hConsole, coordScreen );
 
 return;
}

int main(void)
{
 COORD xy,hv;
 BOOL bContinue=TRUE;
 DWORD dwInputEvents;
 HANDLE hStdOutput,hStdIn;
 INPUT_RECORD ir;

 hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
 hStdIn = GetStdHandle(STD_INPUT_HANDLE);
 cls(hStdOutput);
 xy.X=0;xy.Y=0;
 hv.X=0;hv.Y=1;
 SetConsoleCursorPosition(hStdOutput,xy);
 do
 {
   ReadConsoleInput(hStdIn,&ir,1,&dwInputEvents);
   if(ir.EventType == KEY_EVENT)
   {
      if(ir.Event.KeyEvent.wVirtualKeyCode == VK_ESCAPE)
      {
         printf("%u\t%u\n",VK_ESCAPE,ir.Event.KeyEvent.uChar.AsciiChar);
         break;
      }
      else
      {
         if(ir.Event.KeyEvent.bKeyDown==TRUE)
         {
            if(ir.Event.KeyEvent.dwControlKeyState & RIGHT_CTRL_PRESSED)
               printf("Right Control Key Pressed!\n");
            else
            { 
               switch(ir.Event.KeyEvent.wVirtualKeyCode)
               {
                  case VK_DELETE:
                    printf("%u\tYou Hit Delete!\n",ir.Event.KeyEvent.wVirtualKeyCode);
                    break;
                  case VK_INSERT:
                    printf("%u\tYou Hit Insert!\n",ir.Event.KeyEvent.wVirtualKeyCode);
                    break;
                  case VK_LEFT:
                    printf("%u\tYou Hit The Left Cursor Key!\n",ir.Event.KeyEvent.wVirtualKeyCode);
                    break;
                  case VK_RIGHT:
                    printf("%u\tYou Hit The Right Cursor Key!\n",ir.Event.KeyEvent.wVirtualKeyCode);
                    break;
                  case VK_UP:
                    printf("%u\tYou Hit The Up Cursor Key!\n",ir.Event.KeyEvent.wVirtualKeyCode);
                    break;
                  case VK_DOWN:
                    printf("%u\tYou Hit The Down Cursor Key!\n",ir.Event.KeyEvent.wVirtualKeyCode);
                    break;
                  case VK_NEXT:
                    printf("%u\tYou Hit The Page Down Key!\n",ir.Event.KeyEvent.wVirtualKeyCode);
                    break;
                  case VK_PRIOR:
                    printf("%u\tYou Hit The Page Up Key!\n",ir.Event.KeyEvent.wVirtualKeyCode);
                    break;
                  case VK_HOME:
                    printf("%u\tYou Hit The Home Key!\n",ir.Event.KeyEvent.wVirtualKeyCode);
                    break;
                  case VK_END:
                    printf("%u\tYou Hit The End Key!\n",ir.Event.KeyEvent.wVirtualKeyCode);
                    break;
                  case VK_F1:
                    printf("%u\tYou Hit F1\n",ir.Event.KeyEvent.wVirtualKeyCode);
                    break;
                  case VK_F2: …
Frederick2 189 Posting Whiz

The code below is a Win32 Console program I dug up for you. When it runs it displays the mouse x and mouse y positions on the 2nd line, and the ascii key codes on the 1st line. Run this once and see if it represents progress in the right direction. Note that it is possible to write full fledged 32 bit console programs that do many useful things, but it is a bit unusual. To do it you will have to study the console Api in great detail.

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


void cls(HANDLE hConsole)
{
 CONSOLE_SCREEN_BUFFER_INFO csbi;
 COORD coordScreen = {0,0};
 DWORD cCharsWritten;
 DWORD dwConSize;
 BOOL bSuccess;

 GetConsoleScreenBufferInfo(hConsole,&csbi);
 dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
 FillConsoleOutputCharacter
 (
  hConsole,
  (TCHAR)' ',
  dwConSize,
  coordScreen,
  &cCharsWritten
 );
 GetConsoleScreenBufferInfo(hConsole,&csbi);
 FillConsoleOutputAttribute
 (
  hConsole, 
  csbi.wAttributes,
  dwConSize,
  coordScreen,
  &cCharsWritten
 );
 SetConsoleCursorPosition(hConsole,coordScreen);
 
 return;
}


int main(void)
{
 COORD xy,hv;
 BOOL bContinue=TRUE;
 DWORD dwInputEvents;
 HANDLE hStdOutput,hStdIn;
 INPUT_RECORD ir;

 hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
 hStdIn = GetStdHandle(STD_INPUT_HANDLE);
 cls(hStdOutput);
 xy.X=0;xy.Y=0;
 hv.X=0;hv.Y=0;
 SetConsoleCursorPosition(hStdOutput,xy);
 do
 {
   ReadConsoleInput(hStdIn,&ir,1,&dwInputEvents);
   switch(ir.EventType)
   {
    case KEY_EVENT:
      if(ir.Event.KeyEvent.wVirtualKeyCode==VK_ESCAPE)
      {
         cls(hStdOutput);
         bContinue=FALSE;
      }
      else
      {
        if(ir.Event.KeyEvent.bKeyDown==TRUE)
        {
           SetConsoleCursorPosition(hStdOutput,hv);
           printf
           (
            "Key Event: char=%c\tasci code=%u",
            ir.Event.KeyEvent.uChar.AsciiChar,
            ir.Event.KeyEvent.uChar.AsciiChar
           );
           hv.X=0,  hv.Y=0;
        }
      }
      break;
    case MOUSE_EVENT:
      xy.X=0;xy.Y=1;
      SetConsoleCursorPosition(hStdOutput,xy);
      printf
      (
       "Mouse X = %.3d: Mouse Y = %.3d", 
       ir.Event.MouseEvent.dwMousePosition.X,
       ir.Event.MouseEvent.dwMousePosition.Y
      );
      break;
    default:
      break;
   } 
 }while(bContinue==TRUE);
 
 return 0;
}

I know clearly what you want now. I'll dig up another example for you that is exactly what you want. I actually have a program just like that that creates a button with the …

Frederick2 189 Posting Whiz

AncientDragon wrote...

No you are not. MS-DOS died 10 years ago.

Every year the organization for which I work sells 30 to 45 million dollars worth of timber. This timber is inventoried and tallied using data recorders running my various DOS PowerBASIC, QuickBasic or C programs. So its a pretty healthy corpse I'd say.

Below is just a quick and dirty Win32 Api program for the Dev C++ user. It can be pasted into a new code window in Dev C++ and compiled with either a .c or .cpp extension, I believe (just tested it with .cpp). There should be a couple files of this nature under the Dev C++ installation. I see I must have been experimenting with capturing the delete and/or alt delete key at some point in the past with this program, as it put up a message box when you hit those keys.

#include <windows.h>
#define IDC_BUTTON   WM_USER + 1

LRESULT CALLBACK WndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)
{
 switch (msg)
 {
  case WM_CREATE:
    HINSTANCE hIns;
    HWND hButton;
    hIns=((LPCREATESTRUCT)lParam)->hInstance;
    hButton=
    CreateWindow
    (
     "button",
     "Click Me",
     WS_CHILD|WS_VISIBLE,
     70,60,150,30,
     hwnd,
     (HMENU)IDC_BUTTON,hIns,
     0
    );
    break;
  case WM_COMMAND:
    MessageBox(hwnd,"You Clicked The Button","Message",MB_OK);
    break;
  case WM_KEYDOWN:
    if(wParam==VK_DELETE)
       MessageBox(hwnd,"You Clicked The Delete Key!","Delete!",MB_OK);
    break;
  case WM_SYSKEYDOWN:
    if((lParam&0x20000000)&&wParam==VK_DELETE)
        MessageBox(hwnd,"Alt + Delete Key!","Delete!",MB_OK);
    break;
  case WM_DESTROY:
    PostQuitMessage (0);
    break;
  default:
    return DefWindowProc(hwnd,msg,wParam,lParam);
 }

 return 0;
}

int WINAPI WinMain(HINSTANCE hIns,HINSTANCE hPrevIns,LPSTR lpszArgument,int iShow)
{
 char szClassName[]="WindowsApp";
 WNDCLASSEX wincl; 
 MSG messages;
 HWND hWnd; 

 wincl.hInstance=hIns;
 wincl.lpszClassName=szClassName;
 wincl.lpfnWndProc=WndProc;
 wincl.style=CS_DBLCLKS;
 wincl.cbSize=sizeof (WNDCLASSEX);
 wincl.hIcon=LoadIcon(NULL,IDI_APPLICATION);
 wincl.hIconSm=LoadIcon(NULL, IDI_APPLICATION);
 wincl.hCursor=LoadCursor(NULL,IDC_ARROW); …
Frederick2 189 Posting Whiz

Parsing lines of text like that is pretty mean work if you are just using C string routines such as strtok(). C++ string classes always have string handling/parsing routines similiar to those found in BASIC dialect languages that make this sort of work pretty easy.

Frederick2 189 Posting Whiz

That did it AncientDragon! I knew the key was informing the compiler it was a function call that needed to be set up, not simply a cast, but I couldn't come up with it. I like to fully understand things, you know?

Just in case you're interested, this is what it looks like in PowerBASIC, which is another compiler I use a lot...

#Compile Exe
#Dim All
#Include "Win32Api.inc"
Declare Sub ptrFx()

Function PBMain() As Long
  Local hInstance, dwAddr As Dword

  hInstance=LoadLibrary("DllTest.dll")
  If hInstance Then
     dwAddr=GetProcAddress(hInstance,"Fx")
     Call Dword dwAddr Using ptrFx
     FreeLibrary(hInstance)
  End If

  PBMain=0
End Function

In the above code note 'Declare Sub ptrFx' In the body of PBMain and see how it is used. Call Dword is a PowerBASIC reserved word used to call a function at some/any specific known address. The 'Using' part of the verb tells the compiler what the function looks like so it can set up the function call mechanism. That was really the missing ingredient which you provided for me, that is, some way to let the compiler know its a cdecl function and so on.

Thanks a lot. I'll be studying that!

Fred

Frederick2 189 Posting Whiz

Petzold's books are how I learned Windows Api coding, and the material is still timely and applicable, IMHO. I primarily use Win 2000 and XP and everything in Petzold works fine. Do you have the Windows 95 or 98 book? Actually, there have been some updates to the functions. For example, instead of WNDCLASS you should be using WNDCLASSEX, instead of CreateWindow(), use CreateWindowEx(), etc. That sort of thing. I don't have Vista but people who do told me there isn't much difference regarding the Win32 Api.

Frederick2 189 Posting Whiz

This is my first post! I can’t figure out how to modify/cast the return address obtained from the Windows Api function GetProcAddress() without using a typedef. I’m aware that using a typedef is the standard way to do this, but one should be able to do it without a typedef, shouldn’t one???

I’ll provide a very simple example below for anyone to use if someone would be willing to instruct me on this. Lets make a simple wrapper around the printf function and export it from a dll like so….

//dllWork.cpp
#include <windows.h>
#include <stdio.h>

extern "C" __declspec(dllexport) void Prt(char* msg)
{
 printf("%s\n",msg);
}

This can be compiled with the Microsoft C++ compiler like so…

>cl dllWork.cpp /LD

All it does when called is output to the console the asciiz string passed to it with printf. Below is a host program to explicitely load it and obtain the address of the Prt function with GetProcAddress()…

//Begin  dllHost.cpp
#include <windows.h>
#include <stdlib.h>
typedef void (*FNPTR)(char*);                 <<<note typedef!!!

int main(void)
{
 char szMsg[]="Hello, World!";
 HINSTANCE hIns;
 FNPTR pFn;
 
 hIns=LoadLibrary("dllWork.dll");
 if(hIns)
 {
    pFn=(FNPTR)GetProcAddress(hIns,"Prt");    <<<note use of typedef
    pFn(szMsg);    
    FreeLibrary(hIns);
 }
 system("PAUSE");
  
 return 0;
}

>cl dllHost.cpp

As you can see, it uses a typedef in the customary manner to obtain a usable function pointer out of GetProcAddress(). The program calls Prt in the dll passing it the asciiz string “Hello, World!”.

My question is, “How can this be done without typedef?” I’ve tried for hours, and …