Frederick2 189 Posting Whiz

I just wouldn't have thought a cast would be necessary to assign the results of a division to a floating point variable irregardless of the variable types involved in the division. I'd have expected truncation if the result would be assigned to an integer; but not with a float.

Frederick2 189 Posting Whiz
#include <stdio.h>

int main()
{
 int iBAF=10;
 int iPlots=14;
 double dblFactor;

 dblFactor=iBAF/iPlots;   //to get a floating point you need a cast!
 printf("dblFactor = %10.6f\n",dblFactor);

 return 0;
}

/*
dblFactor =   0.000000
*/

I thought C/C++ would offer a few benifits beyond pure assembler. Apparently I was wrong.

Frederick2 189 Posting Whiz

Good point Tux4Life! I never picked up on that, even though I've been doing this for about 12 years! That point is even described right in the GetMessage documentation. I do believe I may modify my code from now on, but truthfully, I can't say I've ever had a problem with this.

Amazingly, Charles Petzold's books right from Microsoft Press show it the way I have it in my program above. Same with Rector & Newcommer's "Win32 Programming", which is the other major reference on the topic.

Frederick2 189 Posting Whiz

Here is a sample Win32 program for you with directions for setting it up in Visual Studio...

1) Start Visual Studio;
2) Click Create New Project;
3) Highlight C++, Win32 Project;
4) I put mine here >>>> C:\Code\VStudio\VC++9\txtInput;
5) When the Win32 Project – Application Wizard opens choose ‘Windows Application’ and ‘Empty Project’. This is very important! Don’t let Visual Studio write your code for you!!! This is found under ‘Application Settings on the left part of the pane;
6) Click ‘Finish’;
7) Create a file name Form1.h from this…

//Form1.h
#define  IDC_EDIT      2000
#define  IDC_BUTTON    2005

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


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

…and Main.cpp from this, and put them in the Visual Studio txtInput project directory…

//Main.cpp
#include <windows.h>
#include <tchar.h>
#include "Form1.h"
EVENTHANDLER  EventHandler[3];

/*    ******  long fnWndProc_OnCreate(lpWndEventArgs)  ******

  The WM_CREATE message is only received one time for each window
  creation.  The lParam parameter to the message contains a pointer
  to the CREATESTRUCT struct Windows filled out with the data in
  the CreateWindow() call that created the window (in this program
  down in WinMain()).  Just below are two more CreateWindow() calls,
  but these don't create main top level program windows, but rather
  two child window controls, i.e., the edit control and button you
  see when the program run.  The processing in fnWndProc_OnCreate()
  will occur before the CreateWindow() call in WinMain() returns.
  If …
Frederick2 189 Posting Whiz

I most definitely have a book recommendation for you and that is Charles Petzold's "Programming Windows" books. I most imagine all the book links at the top are about C++ specific issues. Creating GUI Windows programs is not a C++ specific issue as others have said.

Even if you choose some class framework to create GUI code, learning just a bit about the lower level Apis is a good idea in both the Windows world and the Linux world.

Ancient Dragon commented: Good book suggestion, I've used it myself and agree with you. +28
Frederick2 189 Posting Whiz

Ya, I had figured out the SetWindowText function, using it under the WM_COMMAND message, but I cant figure out how to make it specific. AKA if I have more then one button, it will change the text of the button handle no matter which of the buttons I click. And I cant switch the wParam under the WM_COMMAND message because I only have handles and no way to ID the buttons.

When you create a button window you should be using equates/defines to save your Ctrl Ids of the child windows ( the HMENU parameter in the CreateWindow() call). I never, never make unique HWND variables for child windows. The equates/defines serve as proxies, so to speak, for the HWNDs because if you know the parent which contains the child window, i.e., in your case a button, you can get the HWND with a call to GetDlgItem() like so...

hButton=GetDlgItem(hParent, IDC_SOME_BUTTON_CONTROL);

Having obtained the hButton you want to change the text on, then just do a SetWindowText() call.

You know, the HWND contained in the HIWORD of wParam I think will also give you this.

Frederick2 189 Posting Whiz

That's really easy. A button, as is just about everything else in Windows, is a 'window'; no pun intended. To change the text associated with many windows you use the SetWindowText() Api function, i.e.,

SetWindowText(hCtl, "Some New Text");

Of course, if you want to change it in response to a click of that specific button, you need to catch the click in your Window Procedure, then change it in the button click handler.

I can post code tomorrow if you don't figure it out in the meantime.

Frederick2 189 Posting Whiz

Will an int in C/C++ now be 8 bytes instead of 4?

printf("sizeof(int) = %u\n", sizeof(int));

sizeof(int) = 8

In DOS it was 2 afterrall.

And what about doubles? Will they be 16 bytes? Maybe call them 'fourples'...

I really don't know. Me and my employeer are stuck in 32 bit XP land.

And another thought....

Last summer I bought VStudio 2008 Pro. Will that install on a Windows 7 64 bit OS and what results will I get with the above printf statement?

Will VStudio 2010 have 32 bit and 64 bit versions? If so, will one version give me a four byte int and the other a 8 byte int???

Frederick2 189 Posting Whiz

so what else do you want me to explain about classes

I don't want you to explain one single thing more about classes! Not One!!!

What I want you to do is create a class to model a box and calculate its volume. Then instantiate an object of this class and calculate the volume of an instance of this class with sides 2, 3, and 4. You can use ints. And I want it done within 24 hours!!!

And I just decided I'm not going to go easy on you!

I also want the program written in C first without classes, and then in C++. Then I want a full elaboration on the differences and why the C++ version might be better!!! And just to show you that I'm a nice guy, I'll add 12 hours to the time limit.

Frederick2 189 Posting Whiz

Seems to me you should be storing the data in a random access binary file. That way you could seek to the record you want. Or arrange the data in memory in such a structure after reading in the text file and then access it randomly by index or something.

Frederick2 189 Posting Whiz

Oooooh! I didn't know that!:)

Frederick2 189 Posting Whiz

Thanks again Ancient Dragon! I'll mark this post as solved because you helped me clarify my thoughts. And, you've been a member here for 4 - 1/2 years * 365 days / year = 1642 days and you've solved 1625 posts so that's about a post per day with only a few sick days per year!

Frederick2 189 Posting Whiz

Thanks a lot for the thoughts and clarification Ancient Dragon. It appears to me almost that a BSTR could be used very similiarly to a VARIANT in Visual Basic where just about anything or maybe even anything could be passed through a BSTR parameter, and it would be up to the receiving function/object to determine what it is and what to do with it. It further appears to me that the various BSTR system string functions plus the length prefixed data would allow the receiving function/object to determine specifically whether a ansi or wide character string is contained in the BSTR. What are your thoughts on this?

That actually is where I'm trying to go with this. I would like to build a GUI Exe COM server in the PowerBASIC programming language, and while that programming language supports the creation of COM dlls very handily, it doesn't natively support the creation of Exe servers. So I'm having to go the low level C route and construct it in a manner very much like in Jeff Glatt's article "COM In Plain C"....

http://www.codeproject.com/KB/COM/com_in_c1.aspx

String data types should be BSTRs so that non-C/C++ clients can easily connect, and it appears to me that within the server I'll need to examine incomming BSTRs to determine whether they are unicode or ansi. I have this server written in C++ and it works fine. What I'm trying to do is translate it to PowerBASIC, and thats where I'm running into …

Frederick2 189 Posting Whiz

Been studying what I thought was a fairly authoritative article about BSTRs by Bruce McKinney...

http://www.ecs.syr.edu/faculty/fawcett/handouts/cse775/Presentations/BruceMcKinneyPapers/COMstrings.htm

where he states that the four bytes before the start of the BSTR contains the string's length. Here is the exact quote...

What Is a BSTR? The BSTR type is actually a typedef, which in typical Windows include file fashion, is made up
of more typedefs and defines. You can follow the twisted path yourself, but here's what it boils down to:

typedef wchar_t * BSTR;

Hmmm. A BSTR is actually a pointer to Unicode characters. Does that look familiar? In case you don't recognize
this, let me point out a couple of similar typedefs:

typedef wchar_t * LPWSTR;
typedef char * LPSTR;

So if a BSTR is just a pointer to characters, how is it different from the null-terminated strings that C++
programmers know so well? Internally, the difference is that there's something extra at the start and end of the
string. The string length is maintained in a long variable just before the start address being pointed to, and the
string always has an extra null character after the last character of the string. This null isn't part of the
string, and you may have additional nulls embedded in the string.

However, my tests prove this to be most untrue. Here is a program with the output directly afterwards where I'm using a simple string as follows for testing purposes...

Frederick2 189 Posting Whiz

I found the solution to this in my "Inside Distributed COM" book by Guy and Henry Eddon. The LCID parameter needs to be LANG_NEUTRAL. That works!

Frederick2 189 Posting Whiz

This is one mean function! I've tried everything I can think of. I registered a type library with LoadTypeLibEx() which is a really easy function to use. I mistakingly thought UnregisterTypeLib() would be routine. Its most decidedly not! The error I keep getting with FormatMessage() is...

Error accessing the OLE registry.

Here is my entire Debug output file from a program run...

Output.txt Opened In WinMain()

Entering ExeUnregisterServer()
  Error accessing the OLE registry.
Leaving ExeRegisterServer()

Exiting WinMain()!

Here is my call to UnregisterTypeLib()...

hr=UnRegisterTypeLib
(
  LIBID_CFLibrary, 
  1, 
  0, 
  LOCALE_USER_DEFAULT, 
  SYS_WIN32
);

Here is the function description from msdn...

UnRegisterTypeLib

HRESULT UnRegisterTypeLib
( 
  REFGUID           libID,             
  unsigned short    wVerMajor,  
  unsigned short    wVerMinor,  
  LCID              lcid,                 
  SYSKIND           syskind            
);
 
Removes type library information from the system registry. Use this API to allow applications to properly 
uninstall themselves. In-process objects typically call this API from DllUnregisterServer.

Parameters

libID        Globally unique identifier. 

wVerMajor    Major version number of the type library being removed. 

wVerMinor    Minor version number of the type library being removed. 

lcid         Locale identifier. There are two predefined LCID values. 
             The system default locale is LOCALE_SYSTEM_DEFAULT, and 
             the current user's locale is LOCALE_USER_DEFAULT.

syskind      The target operating system (SYSKIND). 
             (SYS_WIN16, SYS_WIN32, SYS_MAC)

Return Value

The return value obtained from the returned HRESULT is one of the following:

Return value Meaning 

S_OK                    Success. 
E_OUTOFMEMORY           Out of memory. 
E_INVALIDARG            One or more of the arguments is invalid. 
TYPE_E_IOERROR          The function could not write to the file. 
TYPE_E_REGISTRYACCESS   The system registration database could …
Frederick2 189 Posting Whiz

Focus can be a tricky thing in Windows - as you found out. As I mentioned, your WndProc() wasn't getting the keyboard activity, the WndProc() of the button control was. However, its possible to 'hook' the button WndProc() using the SetWindowLong() function, and in that manner receive the keypresses first in your app. If interested in that look up SetWindowLong() with GWL_WNDPROC parameter. Its called subclassing.

Frederick2 189 Posting Whiz

When you click a button, the focus will change to the button (the button will have keyboard focus). Therefore, any keypresses will be sent to the window procedure of the button, which is in user32.dll I believe. So, you might try using a SetFocus() call back to your main window within the button press event handler so the keystrokes will be sent there instead. I see you are a new poster. If someone solves your problem in this forum, its considered polite to indicate such by marking it solved.

Frederick2 189 Posting Whiz

ProgEx 20, 21, 34, 35, 36 seem to be mostly about file access.

ProgEx 11 is a GetCurrentDirectory() example. Here's the link...

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

Might bo other useful material too.

Frederick2 189 Posting Whiz

I almost forgot about GetCurrentDirectory(). That will give you your current directory without any parsing.

In terms of when you are done with a file, what Windows returns to you is a file HANDLE. You need to use CloseHandle() on that. I consider that to be IMPORTANT.

Unless I have some specific reason to do so, I don't usually use the Windows Api functions for file access, but rather the low level file functions in stdio.h. You might want to take a look at them. I have a tutorial about them if you are interested.

Frederick2 189 Posting Whiz

Use the GetModuleFilename() Api function to get the aformentioned into a buffer and parse it for the path. Then do what you want with it.

Frederick2 189 Posting Whiz

The reason you are not getting any replies Nicholas is because what you are trying to do isn't doable.

Frederick2 189 Posting Whiz

Its executables are also small

What do you mean by small? A year ago I downloaded a wxWidgets demo that had a few GUI elements on it (buttons, listboxes, etc.) and it was around 800K or something like that. A Win32 Sdk style program like that would have been around 20k.

Frederick2 189 Posting Whiz

Recently I've been looking into BSTRs, and have found how 'touchy' they can be. I saw this in a COM class in the class destructor regarding a m_strBStr member...

if(m_strBStr)
   SysFreeString(m_strBStr);

When I saw it I thought, "How would the BSTR have a zero assigned to it?", because I didn't see anywhere in the COM class where that had been done. In fact, I thought it was an illegal operation on a BSTR. However, I wrote a test app to check it, and I'm not getting any crashes...

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

int main(void)
{
 wchar_t* pWideCh=0;
 BSTR strName=0;

 wprintf(L"pWideCh = %u\n",(unsigned)pWideCh);
 wprintf(L"strName = %u\n",(unsigned)strName);
 strName=SysAllocString(L"Fred");
 wprintf(L"strName = %s\n",strName);
 SysFreeString(strName);
 strName=0;
 wprintf(L"strName = %u\n",(unsigned)strName);
 getchar();

 return 0;
}

/*
pWideCh = 0
strName = 0
strName = Fred
strName = 0
*/

Since a BSTR is just a typedef of a wchar_t*, I guess its OK. Could someone let me know for sure?

Frederick2 189 Posting Whiz

I still do a lot of stuff as in C instead of C++, and things like you are doing is one of them. So here's my C solution. You won't hurt my feelings if you don't want it.

#include <stdlib.h>
#include <stdio.h>

/*          Data Looks Like This...
19700326.15 71.37 71.50 70.00 70.50 217600 0.89
19700330.15 70.50 71.00 70.00 71.00 182400 0.90
19700331.15 70.87 70.87 70.62 70.62 177600 0.90
19700401.15 71.12 71.62 71.12 71.12 169600 0.90
       I saved this into file Data.txt
*/

struct Data
{
 double        dblFirst;
 double        dblSecond;
 double        dblThird;
 double        dblFourth;
 double        dblFifth;
 unsigned int  iSixth;
 float         fltSeventh;
};

int main()
{
 char szBuffer[256];
 unsigned int iCt=0;
 Data* pData=NULL;
 FILE* fpIn=NULL;

 fpIn=fopen("Data.txt","r");  //Open "Data.dat for read "r" access.
 if(fpIn)                     //and loop through data to count lines.
 {                            //in iCt
    while(!feof(fpIn))
    {
       fgets(szBuffer,256,fpIn);
       iCt++;
    }
    fclose(fpIn);
 }
 printf("iCt = %d\n\n",iCt);             //Allocate a buffer of Data type
 pData=(Data*)malloc(iCt*sizeof(Data));  //to hold iCt objects
 if(pData)
 {
    fpIn=fopen("Data.txt","r");  //Open "Data.dat for read "r" access.
    if(fpIn)
    {
       iCt=0;
       while(!feof(fpIn))      //read data from text file into buffer
       {
          fscanf(fpIn,"%lf%lf%lf%lf%lf%u%f",
          &pData[iCt].dblFirst,
          &pData[iCt].dblSecond,
          &pData[iCt].dblThird,
          &pData[iCt].dblFourth,
          &pData[iCt].dblFifth,
          &pData[iCt].iSixth,
          &pData[iCt].fltSeventh);
          printf("%10.2f\t%4.2f\t%f\t%f\t%f\t%u\t%4.2f\n",
          pData[iCt].dblFirst,
          pData[iCt].dblSecond,
          pData[iCt].dblThird,
          pData[iCt].dblFourth,
          pData[iCt].dblFifth,
          pData[iCt].iSixth,
          pData[iCt].fltSeventh);
          iCt++;
       }
       fclose(fpIn);
    }
    free(pData);
 }
 getchar();

 return 0;
}

/*     Output
============================================
iCt = 4

19700326.15     71.37   71.500000       70.000000       70.500000       217600  0.89
19700330.15     70.50   71.000000       70.000000       71.000000       182400  0.90
19700331.15     70.87   70.870000       70.620000       70.620000       177600  0.90
19700401.15     71.12   71.620000       71.120000       71.120000       169600  0.90
*/
Frederick2 189 Posting Whiz

I'd be really leery of returning a stack based temporary variable to a caller as you are doing.

Frederick2 189 Posting Whiz

Maybe its just me, but that strikes me as a strange thing to do. Far easier to just put a text box on a form at design time, and retrieve data out of it if the user enters any.

Frederick2 189 Posting Whiz

Couldn't be easier...

Form1.h

//Form1.h
#define  IDC_EDIT      2000
#define  IDC_BUTTON    2005

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


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

Main Source File

//Main.cpp
#include <windows.h>
#include <tchar.h>
#include "Form1.h"
EVENTHANDLER  EventHandler[3];


long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
 HWND hCtrl;

 Wea->hIns=((LPCREATESTRUCT)Wea->lParam)->hInstance;
 hCtrl=
 CreateWindowEx
 (
  WS_EX_CLIENTEDGE,
  "edit","",WS_CHILD|WS_VISIBLE,
  10,30,270,30,
  Wea->hWnd,
  (HMENU)IDC_EDIT,
  Wea->hIns,
  0
 );
 hCtrl=
 CreateWindow
 (
  "button",
  "Click Me",
  WS_CHILD|WS_VISIBLE,
  70,80,150,30,
  Wea->hWnd,
  (HMENU)IDC_BUTTON,
  Wea->hIns,
  0
 );

 return 0;
}


long fnWndProc_OnCommand(lpWndEventArgs Wea)
{
 switch(LOWORD(Wea->wParam))
 {
   case IDC_BUTTON:
   {
     TCHAR szBuffer[256];
     GetWindowText(GetDlgItem(Wea->hWnd,IDC_EDIT),szBuffer,256);
     MessageBox
     (
      Wea->hWnd,
      szBuffer,
      _T("Here Is The Text You Entered"),
      MB_OK
     );
   }
 }

 return 0;
}


long fnWndProc_OnClose(lpWndEventArgs Wea)
{
 DestroyWindow(Wea->hWnd);
 PostQuitMessage(0);
 return 0;
}


void AttachEventHandlers(void)
{
 EventHandler[0].Code=WM_CREATE;
 EventHandler[0].fnPtr=fnWndProc_OnCreate;
 EventHandler[1].Code=WM_COMMAND;
 EventHandler[1].fnPtr=fnWndProc_OnCommand;
 EventHandler[2].Code=WM_CLOSE;
 EventHandler[2].fnPtr=fnWndProc_OnClose;
}


long __stdcall fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam,LPARAM lParam)
{
 WndEventArgs Wea;

 for(unsigned int i=0; i<3; i++)
 {
     if(EventHandler[i].Code==msg)
     {
        Wea.hWnd=hwnd, Wea.lParam=lParam, Wea.wParam=wParam;
        return (*EventHandler[i].fnPtr)(&Wea);
     }
 }

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


int __stdcall WinMain(HINSTANCE hIns, HINSTANCE hPrevIns, LPSTR lpszArgument, int iShow)
{
 TCHAR szClassName[]=_T("Form1");
 WNDCLASSEX wc;
 MSG messages;
 HWND hWnd;

 AttachEventHandlers();
 wc.lpszClassName=szClassName;
 wc.lpfnWndProc=fnWndProc;
 wc.cbSize=sizeof (WNDCLASSEX);
 wc.style=CS_DBLCLKS;
 wc.hIcon=LoadIcon(NULL,IDI_APPLICATION);
 wc.hInstance=hIns;
 wc.hIconSm=LoadIcon(NULL, IDI_APPLICATION);
 wc.hCursor=LoadCursor(NULL,IDC_ARROW);
 wc.hbrBackground=(HBRUSH)COLOR_BTNSHADOW;
 wc.cbWndExtra=0;
 wc.cbClsExtra=0;
 wc.lpszMenuName=NULL;
 RegisterClassEx(&wc);
 hWnd=CreateWindowEx(0,szClassName,_T("Enter Text In Text Box"),WS_OVERLAPPEDWINDOW,100,100,300,175,HWND_DESKTOP,0,hIns,0);
 ShowWindow(hWnd,iShow);
 while(GetMessage(&messages,NULL,0,0))
 {
    TranslateMessage(&messages);
    DispatchMessage(&messages);
 }

 return messages.wParam;
}
Frederick2 189 Posting Whiz

I don't feel you've given enough information. Are you trying to write a console mode or GUI ( Graphical User Interface ) program?
Both are Win32. Console mode programs mostly use the exported functions in Kernel32.lib and GUI programs User32 and GDI.

Frederick2 189 Posting Whiz

This is the "Data.dat" file i made from your data and saved as a text file in the same dir as the executable...

["link"] = "|cff1eff00|Hitem:7931:0:0:0:0:0:0:0:80|h[Mithril Coif]|h|r",},[45] = {["count"] = 1000,
["link"] = "|cff0070dd|Hitem:41165:0:0:0:0:0:0:0:80|h[Saronite Razorheads]|h|r",

Here is "Main.cpp" which is the main source file (not counting the String class in "Strings.h" and "Strings.cpp" to follow). Note I used CodeBlocks to create this. It is free software and very good. I actually prefer it to my Visual Studio 2008 Pro, which just puts you through a lot more hassle to start a project. Since I start a lot of small projects for testing purposes, that is a big issue for me. Anyway, if you are using Visual Studio you'll likely get piles of _CRT_SECURE_NO_WARNINGS. These can be turned off by pasting the above in the pre-processor definitions.

#include <tchar.h>
#include <stdio.h>
#include "Strings.h"

int main()
{
 char szBuffer[200];
 unsigned int iLn,iLn1;
 FILE* fp=NULL;
 String strLn;
 String* pLn1;
 String* pLn;

 fp=fopen("Data.dat","r");
 if(fp)
 {
    while(!feof(fp))
    {
       fgets(szBuffer,160,fp);
       strLn=szBuffer;
       iLn=strLn.ParseCount('|');
       printf("%d\t%s\n",iLn,szBuffer);
       pLn=new String[iLn];
       strLn.Parse(pLn,'|');
       for(unsigned int i=0; i<iLn; i++)
       {
           if(i==2)
           {
              iLn1=pLn[i].ParseCount(':');
              pLn1=new String[iLn1];
              pLn[i].Parse(pLn1,':');
              printf("\n\tThe Number You Are Looking For Is %s\n\n",pLn1[1].lpStr());
              delete [] pLn1;
           }
           printf("%u\t%s\n",i,pLn[i].lpStr());
       }
       delete [] pLn;
       printf("\n\n");
    }
    fclose(fp);
 }

 return 0;
}

/*
Output
==========================================================================================================

6       ["link"] = "|cff1eff00|Hitem:7931:0:0:0:0:0:0:0:80|h[Mithril Coif]|h|r",},[45] = {["count"] = 1000,

0       ["link"] = "
1       cff1eff00

        The Number You Are Looking For Is 7931

2       Hitem:7931:0:0:0:0:0:0:0:80
3       h[Mithril Coif]
4       h
5       r",},[45] = {["count"] = 1000,



6       ["link"] = …
jonsca commented: Great Effort! +2
Frederick2 189 Posting Whiz

Just to see what happens, why don't you try a fully qualified path? With constructs such as you are using, its usually GetProcAddress() that causes trouble - not LoadLibrary().

Frederick2 189 Posting Whiz

Well, I'm not sure where the line breaks are in the above blurb you posted, and that would likely be critical information. That's why I asked you to attach a real file with just a few lines.

But since everybody is talking external libraries or other languages (in terms of other languages, if one were to attempt to come up with a worse language than C++ for this sort of work, one would be really up against it to find one. The only thing that comes to my mind would be assembler), I used PowerBASIC ( www.powerbasic.com ), which is my main programming language for desktop Windows. So, assumming this data in a text file named Data.dat, here is the PowerBASIC program that parses it based on the pipe character as a delimiter, i.e., "|"

["link"] = "|cff1eff00|Hitem:7931:0:0:0:0:0:0:0:80|h[Mithril Coif]|h|r",},[45] = {["count"] = 1000,
["link"] = "|cff0070dd|Hitem:41165:0:0:0:0:0:0:0:80|h[Saronite Razorheads]|h|r",

1st code followed by output...

#Compile Exe
#Dim All

Function PBMain() As Long
  Local fp As Integer
  Local strLn As String
  Local iLn As Long

  fp=Freefile
  Open "Data.dat" For Input As #fp
  Do While Not Eof(fp)
     Line Input #fp, strLn
     iLn=ParseCount(strLn,"|")
     Print iLn,strLn
  Loop
  Close #fp
  Waitkey$

  PBMain=0
End Function

'Output
'=================================================================================================================
' 6            ["link"] = "|cff1eff00|Hitem:7931:0:0:0:0:0:0:0:80|h[Mithril Coif]|h|r",},[45] = {["count"] = 1000,
' 6            ["link"] = "|cff0070dd|Hitem:41165:0:0:0:0:0:0:0:80|h[Saronite Razorheads]|h|r",

What the above program indicates is that there are six (6) pipe "|" delimited fields in each line. Next step we'll actually parse the lines based on that delimiter...


       
Frederick2 189 Posting Whiz

I've never done it here but you can apparently attach files. If you can whittle your file down to just a few K, and identify the data you would like parsed out, I'll see what I can do.

Frederick2 189 Posting Whiz

That's confusing looking data. Does every line have the same structure (even though the data is different) with the same number of delimiters? I'm seeing pipe characters which you mentioned were being used as delimiters, but I'm also seeing commas.

Frederick2 189 Posting Whiz

Just one more thought. Assumming GetUpdateRect() works, the only context in which I can see it being used for something like you want is to launch a seperate thread of execution that polls with the function so that you'll get a continuous reading of update regions for whatever purpose you need them. If you had written the app which will be doing the screen updating, then I'd say either broadcast a custom message to other apps, or signal a mutex which could be WaitForSingleObject()'ed on. But I'm not sure you have a cooperating object in mind.

Frederick2 189 Posting Whiz

I just looked at MSDN for GetUpdateRect(). It doesn't say anything about the window having to be in your process, so right now I'm thinking that if you can get the hWnd of the window you want the update rectangle for, you could get it with the above described function. Getting the update region is probably not viewed by Windows as being nearly as invasive as hooking it as I was trying to do. Maybe later if I have time I'll try to modify my program to see if I can get it to work that way. Might want to check out GetUpdateRgn(). I havn't looked at it, but it sounds promising.

Frederick2 189 Posting Whiz

I expect what you are attempting to do does not involve a process created by your program, so my idea about subclassing won't work. I found this as the 1st line in the remarks for SetWindowLong()...

Remarks

The SetWindowLong function fails if the window specified by the hWnd parameter does not belong to the same process as the calling thread.

In the example I posted, while I was able to get the hWnd of the desktop, Windows would not let me subclass it and returned an "ACCESS VIOLATION" error at my attempt. I tend to doubt Windows will allow you to intercept WM_PAINT messages for any Window not in your process.

I've no experience with the software you are describing; never even heard of it. Nor have I ever tried anything like you are describing. However, if you have an application with various Windows, and its one of those, i.e., your windows in your process, that you want to obtain the update region for, then I'd say that's doable. However, if you are wanting to get the update region for some window not in your process, such as the Windows desktop, well, I don't know how to do that. Maybe someone else knows.

Frederick2 189 Posting Whiz

I'm glad you're off the DESKTOP Window theme. That made me uneasy. I kind of figgured it was a 'special' window where speciial rules might apply, and my tests seemed to bear that out. What other coders do I'm not sure, but I never mess with the desktop.

In terms of getting handles to other windows, the various Enum functions are useful for that, e.g., EnumChildWindows, EnumWindows, etc.

Frederick2 189 Posting Whiz

Well, I took a shot at it and failed. However, I'll post the code I got. What seems to be happening is that Windows isn't allowing me to subclass the desktop window. When I call GetLastError() after the call to SetWindowLong() that would set the subclass proc - here MyDesktopHook(), I'm getting the error #5 which is "ACCESS DENIED".

So my subclass isn't working. Perhaps I've a dumb error; was coding pretty fast. Anyway here's the code and I've a tutorial on subclassing here...

http://www.jose.it-berater.org/smfforum/index.php?topic=3392.0

Check Out ProgEx40f

//Form1.h

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


struct EVENTHANDLER
{
 unsigned int    Code;
 long            (*fnPtr)(lpWndEventArgs);
};
//Main.cpp
#include <windows.h>
#include <stdio.h>
#include "Form1.h"
EVENTHANDLER  EventHandler[3];
WNDPROC fnDesktopProc=0;
FILE* fp;

long __stdcall fnMyDesktopHook(HWND hwnd, unsigned int msg, WPARAM wParam,LPARAM lParam)
{
 if(msg==WM_PAINT)
    fprintf(fp,"Got WM_PAINT Message For Desktop Window!\n");
 else
    fprintf(fp,"Got Something Else!\n");

 return CallWindowProc(fnDesktopProc,hwnd,msg,wParam,lParam);
}



long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
 HWND hDesktop;

 fp=fopen("Output.txt","w");
 fprintf(fp,"Entering fnWndProc_OnCreate()\n");
 fprintf(fp,"  Output.txt Opened In fnWndProc_OnCreate()\n");
 hDesktop=GetDesktopWindow();
 fprintf(fp,"  hDesktop = %u\n",hDesktop);
 if(hDesktop)
 {
    fnDesktopProc=(WNDPROC)SetWindowLong(hDesktop,GWL_WNDPROC,(long)fnMyDesktopHook);
    fprintf(fp,"  GetLastError() = %u\n",GetLastError());
    fprintf(fp,"  fnDesktopProc = %u\n",(unsigned)fnDesktopProc);
 }
 fprintf(fp,"Leaving fnWndProc_OnCreate()\n\n");

 return 0;
}

long fnWndProc_OnLButtonDown(lpWndEventArgs Wea)
{
 RedrawWindow(NULL,NULL,NULL,RDW_INVALIDATE|RDW_UPDATENOW|RDW_ALLCHILDREN);
 return 0;
}


long fnWndProc_OnClose(lpWndEventArgs Wea)
{
 HWND hDesktop;
 fprintf(fp,"Entering fnWndProc_OnClose()\n");
 hDesktop=GetDesktopWindow();
 if(fnDesktopProc)
    SetWindowLong(hDesktop,GWL_WNDPROC,(long)fnDesktopProc);
 DestroyWindow(Wea->hWnd);
 PostQuitMessage(0);
 fprintf(fp,"  Output.txt Closed In fnWndProc_OnClose()\n");
 fprintf(fp,"Leaving fnWndProc_OnClose()\n\n");
 fclose(fp);

 return 0;
}


void AttachEventHandlers(void)         //This procedure maps windows messages to the
{                                      //procedure which handles them.
 EventHandler[0].Code=WM_CREATE,       EventHandler[0].fnPtr=fnWndProc_OnCreate;
 EventHandler[1].Code=WM_LBUTTONDOWN,  EventHandler[1].fnPtr=fnWndProc_OnLButtonDown;
 EventHandler[2].Code=WM_CLOSE,        EventHandler[2].fnPtr=fnWndProc_OnClose;
}


long __stdcall fnWndProc(HWND hwnd, …
Frederick2 189 Posting Whiz

I've never tried it with the desktop window, but what I'm going to say might work with the desktop window, unless its some special case and is disallowed there. If you can get the hwnd of any window (and you can get the hwnd of the desktop), you can 'hook' the internal window procedure of the window by setting an address of a WNDPROC you've created in your app in the chain of window procedures windows calls when a message is destined for that window. The technique is known as subclassing, and while it sounds complicated; it isn't. You use SetWindowLong() with the GWL_WNDPROC in the 2nd parameter. In that way you might be able to retrieve the update regions from the desktop. To me, it seems pretty bizarre and I don't do stuff like that (trying to mess around with Windows Desktop), but you might look into it. Search on Window Subclassing and SetWindowLong(). If you are interested I'll dig up an example.

Frederick2 189 Posting Whiz

No, that's my own style Win32 program. I don't use MFC.

I've no experience with what you are trying to do, but I can say for absolute certainty that you can't use the WM_PAINT message of one window to draw into another. Just recently there was a post about this in the PowerBASIC forums. While I realize you are doing C++, discussions of this nature about how the Windows Api work are rather language agnostic, as the Api can be used from any number of different languages. Here is the link...

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

Frederick2 189 Posting Whiz

Usually in my WM_PAINT handlers I just declare a...

PAINTSTRUCT ps;

...instead of a LPPAINTSTRUCT. However, that might be just me. When you do declare a LPPAINTSTRUCT though, this...

hDC=BeginPaint(hwnd,&lpPS);

won't work. I'd just do this...

PAINTSTRUCT ps;
HDC hDC;

hDC=BeginPaint(hwnd,&ps);

Here's a little program that demonstrates invalid regions by opening a text file in whatever directory you are running the program from, and outputs invalid regions as you move another window on top of the client window. Experiment by opening Notepad and resizing it to pretty small. Then move Notepad just barely over your client window, then close out and inspect your Output.txt file.

//Form1.h

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


struct EVENTHANDLER
{
 unsigned int    Code;
 long            (*fnPtr)(lpWndEventArgs);
};
//Main.cpp
#include <windows.h>
#include <stdio.h>
#include "Form1.h"
EVENTHANDLER  EventHandler[3];
FILE* fp;


long fnWndProc_OnCreate(lpWndEventArgs Wea)
{
 fp=fopen("Output.txt","w");
 fprintf(fp,"Entering fnWndProc_OnCreate()\n");
 fprintf(fp,"  Output.txt Opened In fnWndProc_OnCreate()\n");
 fprintf(fp,"Leaving fnWndProc_OnCreate()\n\n");

 return 0;
}

long fnWndProc_OnPaint(lpWndEventArgs Wea)
{
 PAINTSTRUCT ps;
 HDC hDC;

 fprintf(fp,"Entering fnWndProc_OnPaint()\n");
 hDC=BeginPaint(Wea->hWnd,&ps);
 fprintf(fp,"  ps.rcPaint.left   = %u\n",(unsigned)ps.rcPaint.left);
 fprintf(fp,"  ps.rcPaint.top    = %u\n",(unsigned)ps.rcPaint.top);
 fprintf(fp,"  ps.rcPaint.right  = %u\n",(unsigned)ps.rcPaint.right);
 fprintf(fp,"  ps.rcPaint.bottom = %u\n",(unsigned)ps.rcPaint.bottom);
 EndPaint(Wea->hWnd,&ps);
 fprintf(fp,"Leaving fnWndProc_OnPaint()\n\n");

 return 0;
}


long fnWndProc_OnClose(lpWndEventArgs Wea)
{
 fprintf(fp,"Entering fnWndProc_OnClose()\n");
 DestroyWindow(Wea->hWnd);
 PostQuitMessage(0);
 fprintf(fp,"  Output.txt Closed In fnWndProc_OnClose()\n");
 fprintf(fp,"Leaving fnWndProc_OnClose()\n\n");
 fclose(fp);

 return 0;
}


void AttachEventHandlers(void)         //This procedure maps windows messages to the
{                                      //procedure which handles them.
 EventHandler[0].Code=WM_CREATE,       EventHandler[0].fnPtr=fnWndProc_OnCreate;
 EventHandler[1].Code=WM_PAINT,        EventHandler[1].fnPtr=fnWndProc_OnPaint;
 EventHandler[2].Code=WM_CLOSE,        EventHandler[2].fnPtr=fnWndProc_OnClose;
}


long __stdcall fnWndProc(HWND hwnd, unsigned int msg, WPARAM wParam,LPARAM lParam) …
Frederick2 189 Posting Whiz

The invalid region is contained within the RECT member (.rcPaint) of the PAINTSTRUCT you used as an output parameter in the BeginPaint() call. It can be easily retrieved from there.

I wrote the above without looking at your code. All your code is totally bad. You are using BeginPaint() incorrectly. You need to declare a PAINTSTRUCT variable in your WM_PAINT handler. Its address should be the 2nd parameter of BeginPaint(). When BeginPaint() returns, you'll not only have the HDC you need, but also the coordinates of the invalid rectangle that needs painted. Its up to you what you do with this information. Passing a NULL as the 2nd parameter of BeginPaint() is something I've never seen done. Your BeginPaint() call would certainly have failed.

Also, I'd be ashamed posting code with such poor formatting.

Frederick2 189 Posting Whiz

In Petzold's book he has a chapter on Dll in the Win32 environment. Also, this is a pretty good article, which was originally on my MSDN CDs for Visual Studio 6...

http://iaci.unq.edu.ar/materias/laboratorio2/Dll/DLLs%20for%20Beginners.pdf

Frederick2 189 Posting Whiz

Might be something useful to you here...

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

Starting around ProgEx13 on up to #18 or 19 is a lot of stuff on dlls and mixed language programming with C++ - PowerBASIC and vice versa.

http://www.jose.it-berater.org/smfforum/index.php?topic=3335.0

Lot of advanced WinApi and COM stuff at that site.

Frederick2 189 Posting Whiz

Yea, that's great ... until the lights go out unexpectently :) But that wouldn't matter if the database is read-only anyway, or immediately saves changes to disk on updates.

Otherwise that was an excellent article.

I did some reading up on Office 2010 which apparently has the 32 bit & 64 bit bundled together, and the default installation is 32 bit which is somehow jerry rigged to supposedly have the same limits as the 64 bit (don't know how that could be?) so why install the 64 bit, as the 64 bit has some compatibility problems with 32 bit apps so that's why the default installation is 32 bit, but you can install the 64 bit if you want, etc......

yea, I'm confused too!!!

Frederick2 189 Posting Whiz

Guess I should have figured lots of other folks are wondering the same thing and googled it. Found some good info here...

http://www.easysoft.com/developer/interfaces/odbc/64-bit.html

Ancient Dragon commented: excellent link +26
Frederick2 189 Posting Whiz

Does anyone know if there are any issues in using the basic ODBC Api for database access on 64 bit Windows Vista/7 systems? This has been my preferred database access technology for a long time, and I'd prefer not moving to ADO or something else if I don't have to. It'll probably be more than a year before my organization moves off 32 bit XP, but I'm kind of looking ahead. For that matter, I don't even know if ODBC was ported (if that's the right word) to 64 bit. Anyone know about this or have some links?

Frederick2 189 Posting Whiz

Well, that doesn't cause the compilation to fail; it just causes piles of blasted warnings. I've been satisfactorily using Salem's suggestion ever since with no problems.

I tend to not use Visual Studio though for reasons such as this. Its basically a pain the whole routine one must go through to use it. My routine to set up a project is to first tell it not to make Debug builds, because I don't use debuggers. That takes a number of mouse clicks. Then I've got to sift through the various configuration options to paste the CRT_SECURE_NO_WARNINGS in the right place. Might be a few more things that need done too, depending if I want to use ansi instead of UNICODE. And of course the whole thing is slow and ponderous because its based on bloatware from Microsoft.

Of course, the ultimate solution to the CRT_SECURE_NO_WARNINGS is to use the SECURE versions of the string buffer minipulation routines I use so much and not the 'insecure' versions I've grown accustomed to since the early stone age. But hey! I hate to change! Anyway, about all I use C++ for is Windows CE programs and playing with COM. The data recorders my Windows CE programs run on aren't networked or connected to the internet so its a non point.

For reasons such as this though I prefer other development environments. I needed the Visual Studio software and I'm glad I have it. When I have a choice though I …

Frederick2 189 Posting Whiz

I feel your question is a bit vague, so I'm afraid my answer will necessarily also be vague. If your classes have nothing whatsoever to do with I/O then you'll need to change nothing. However, if any of them do console I/O, then you've got problems.