I fixed a few more of your multitudinous errors
#include <windows.h>
#include <windowsx.h>
//WinProc Function prototype
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam);
//entry point for any windows program
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
wchar_t szClassName[]=L"WindowsClass1";
//window handle
HWND hWnd;
//holds informaintion for windows class
WNDCLASSEXW wc;
//clear windows were using
ZeroMemory(&wc, sizeof(WNDCLASSEXW));
//WC structure data
wc.cbSize = sizeof(WNDCLASSEXW);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = szClassName; //You can't assign a char array with = sign!
RegisterClassExW(&wc); //you forgot to register the window class
//generate the window
hWnd = CreateWindowExW(0, L"WindowsClass1", L"Windows Form Frame 1", WS_OVERLAPPEDWINDOW, 300, 300, 500, 400, NULL, (HMENU)NULL, hInstance, 0);
//Show generated Window
ShowWindow(hWnd, nCmdShow);
MSG msg;
// wait for the next message in the queue, store the result in 'msg'
while(GetMessageW(&msg, NULL, 0, 0))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);
// send the message to the WindowProc function
DispatchMessageW(&msg);
}
// return this part of the WM_QUIT message to Windows
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// sort through and find what code to run for the message given
switch(message)
{
// this message is read when the window is closed
case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return 0;
} break;
}
// Handle any messages the switch statement didn't
return DefWindowProcW (hWnd, message, wParam, lParam); …
I've fixed your program so that it will at least compile and run AltXError. You made a lot of serious errors. I consider this to be a very poor attempt at something that is rather exacting. I'd encourage you to study harder and be more careful. Here is your somewhat repaired program. It still isn't exactly right, but its closer.
#include <windows.h>
#include <windowsx.h>
//WinProc Function prototype
LRESULT CALLBACK WindowProc (HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam);
//entry point for any windows program
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
wchar_t szClassName[]=L"WindowsClass1";
//window handle
HWND hWnd;
//holds informaintion for windows class
WNDCLASSEXW wc;
//clear windows were using
ZeroMemory(&wc, sizeof(WNDCLASSEX));
//WC structure data
wc.cbSize = sizeof(WNDCLASSEXW);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = (HBRUSH)COLOR_WINDOW;
wc.lpszClassName = szClassName;
RegisterClassExW(&wc);
//generate the window
hWnd = CreateWindowExW(0, L"WindowsClass1", L"Windows Form Frame 1", WS_OVERLAPPEDWINDOW, 300, 300, 500, 400, NULL, (HMENU)NULL, hInstance, 0);
//Show generated Window
ShowWindow(hWnd, nCmdShow);
MSG msg;
// wait for the next message in the queue, store the result in 'msg'
while(GetMessage(&msg, NULL, 0, 0))
{
// translate keystroke messages into the right format
TranslateMessage(&msg);
// send the message to the WindowProc function
DispatchMessage(&msg);
}
// return this part of the WM_QUIT message to Windows
return msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// sort through and find what code to run for the message given
switch(message)
{
// this message …
Here is a tutorial that might help...
http://www.jose.it-berater.org/smfforum/index.php?topic=3389.0
The first problem I saw in your code is that you foreward declare WinProc, but you named your actual Window Procedure 'WindowProc', and so when you used the term ...
wc.lpfnWndProc = WindowProc;
...it was unrecognized by the compiler (it wasn't foreward declared.
Also, the 10th parameter of the CreateWindowEx() call should have a cast like so...
...,(HMENU)NULL,...
Just spotted your first error about the int. You didn't put a semicolon after this declare...
LRESULT CALLBACK WinProc (HWND hWnd, UINT message, WPARAM wparam, LPARAM lparam)
...so it gave an error on the next line. So you've a lot of problems here.
Here is a tutorial that might help...
http://www.jose.it-berater.org/smfforum/index.php?topic=3389.0
The first problem I saw in your code is that you foreward declare WinProc, but you named your actual Window Procedure 'WindowProc', and so when you used the term ...
wc.lpfnWndProc = WindowProc;
...it was unrecognized by the compiler (it wasn't foreward declared.
Also, the 10th parameter of the CreateWindowEx() call should have a cast like so...
...,(HMENU)NULL,...
Your basic console mode "Hello, World!" program comes in around 6 K using stdio.h and printf and anywhere between 250 K - 500 K using iostream and std::cout. For these reasons I never use iostream. I do console output with printf. Anyway, iostream isn't particularly useful in GUI.
Wide character strings are pretty much necessary, and if I were you I'd give up on using both the char data type and the wchar_t data type in favor of the TCHAR data type and the tchar.h macros (if you are using Windows, that is!). If you are going to interoperate between null terminated character buffers and the std::string or std::wstring classes you are going to have to get used to declaring instances of both and moving strings between them.
Like tonyjv intimated, I don't think its terribly useful to invest time in DOS coding at this point.
Having said that however, its possible to create quite a lot of GUI like 'controls' in DOS using the extended asci characters. A lot of us old time DOS coders did that before Win32 took over. For example, when I was learning assembler and C many years ago I made my own 'Open File' dialog box with recursive directory searches, scroll bars and such - all mousable. Using the Int 33h mouse interrupts you can create mousable programs. The old DOS style menues where you have a number for a selection, i.e.,
1) Open File
2) Calculate Volumes
3) Print Report
.
etc
can be made mousable by highlighting each selection as the mouse is moved over it. So on and soi forth.
For myself, I can't really see ever going back to something like that.
Here's just another thought though. I don't want to cause any language flamewars here, but I happen to divide my coding pretty evenly between the C/C++ and PowerBASIC languages. PowerBASIC has a product called the 'Console Compiler' that takes old DOS BASIC code and compiles it into 32 bit Win executables. I'm mentioning this because it wouldn't surprise me to learn that some of your boss's old programs were in some version of BASIC such as QuickBasic, TurboBasic PDS 7.1 or something like that. The executables produced by this language are as …
I find it hard to believe you are finding it hard to find links on ODBC. Here is a Wikipedial link...
http://en.wikipedia.org/wiki/Open_Database_Connectivity
I imagine wxWidgets must have some class wrappers on ODBC. If not you can use what I provided as a start. All those databases you listed in your first post are supported for sure. The beauty of ODBC is that you can use close to the same code for all. I say 'close to the same' because the standards allow for different levels of support. ODBC contains various functions that query the underlying proprietary database driver for functionalities supported. In that way your code can act appropriately to the context of its present environment.
I've posted various tutorial material on the subject in various places. Here is about the same as I posted here but in C instead of C++, but I believe the code is somewhat more heavily commented...
http://www.powerbasic.com/support/pbforums/showthread.php?t=24912&highlight=ODBC+Demo
And here is a rather complex demo that is GUI but shows how to connect to Microsoft SQL Server, Microsoft Access, and Microsoft Excel. Also, it shows how to use SQLDrivers() to dump the ODBC database drivers on your system....
http://www.jose.it-berater.org/smfforum/index.php?board=378.0
As I mentioned, I never tried it on Linux. I have Ubuntu too; just never checked it out. These ODBC functions (the ODBC Api) should work exactly the same on Linux/Unix as on Windows though. If you get it working with My Sql or anything like that I'd appreciate knowing how to change or add to my cnnection string wrappers so as to include it so to speak. The way things are set up now, I have that MakeConnectionString() function...
void SQL::MakeConnectionString(void)
{
if(strDriver==_T("SQL Server"))
{
if(strDBQ==_T(""))
{
strConnectionString=_T("DRIVER=");
strConnectionString=strConnectionString+strDriver+_T(";")+_T("SERVER=")+strServer+_T(";");
}
else
{
strConnectionString=_T("DRIVER=");
strConnectionString=strConnectionString+strDriver+_T(";")+_T("SERVER=")+strServer+_T(";")+ \
_T("DATABASE=") + strDatabase + _T(";") + _T("DBQ=") + strDBQ + _T(";");
}
}
else if(strDriver==_T("Microsoft Access Driver (*.mdb)"))
{
strConnectionString=_T("DRIVER=");
strConnectionString=strConnectionString+strDriver+_T(";")+_T("DBQ=")+strDBQ+_T(";");
}
else if(strDriver==_T("Microsoft Excel Driver (*.xls)"))
{
strConnectionString=_T("DRIVER=");
strConnectionString=strConnectionString+strDriver+_T(";")+_T("DBQ=")+strDBQ+_T(";");
}
}
where you choose SQL Server, Microsoft Access Driver, or Excel Driver, and that function puts together a connection string. That's the function that needs added to to support other databases.
When I first learned …
Here's how I'd do it. First make a text file and put about 10 numbers in it and call it Data.txt...
1
5
34
65
2
7
897
123
36
67
#include <stdio.h>
const int SIZE_ARRAY=500;
int main()
{
int ar[SIZE_ARRAY];
int iNum=0,iCtr=0;
FILE* fp=NULL;
fp=fopen("Data.txt","r");
if(fp)
{
printf("iCtr\tar[iCtr]\n");
printf("================\n");
while(true)
{
fscanf(fp,"%d",&iNum);
if(feof(fp))
break;
if(iCtr<SIZE_ARRAY)
ar[iCtr]=iNum;
printf("%d\t%d\n",iCtr,ar[iCtr]);
iCtr++;
};
fclose(fp);
}
return 0;
}
Here's the output...
iCtr ar[iCtr]
================
0 1
1 5
2 34
3 65
4 2
5 7
6 897
7 123
8 36
9 67
And here's a better version using pointers where you don't have to care about how many items are in the file at all...
//this version dynamically allocates memory for
//number of ints in file Data.txt
#include <stdio.h>
int main()
{
int* pInt=NULL;
int iNum=0,iCtr=0;
FILE* fp=NULL;
fp=fopen("Data.txt","r");
if(fp)
{
while(true) //1st find out how many ints in file
{
fscanf(fp,"%d",&iNum);
if(feof(fp))
break;
iCtr++;
};
pInt=new int[iCtr]; //allocate memory for iCtr ints
rewind(fp); //rewind file
printf("i\tpInt[i]\n");
printf("===============\n");
for(int i=0; i<iCtr; i++)
{
fscanf(fp,"%d",&iNum);
pInt[i]=iNum;
printf("%d\t%d\n",i,pInt[i]);
};
fclose(fp);
delete [] pInt;
}
return 0;
}
Output...
i pInt[i]
===============
0 1
1 5
2 34
3 65
4 2
5 7
6 897
7 123
8 36
9 67
...which is the general way of dealing with this sort of thing, as I originally stated.
AFAIK, Odbc is not part of C++ standard so it is neither in Mingw or Linux GCC. So where do I download headers/sources to compile? Or even ready .a and .h?
In terms of relational databases, what is in the C++ standard? My guess is nothing, but don't rely on me as being knowledeable about the C++ standard because I've never read it.
Having said that I've never used a Windows computer nor a 32 bit programming language where I couldn't easily use ODBC to connect to relational databases, among other things. I use PowerBASIC a lot...
and they have headers that allow me to use ODBC. Years ago I used to use the GNU / Bloodshed Dev-C++ and the necessary libs and headers were installed as part of the default install. Likewise Visual Studio 6 (circa 1999), and Visual Studio 2008. I now use the new cross platform Code::Blocks a lot too. That code I just posted was written in CodeBlocks.
The most basic Windows installation will install ODBC drivers for most databases; I'm even pretty sure for Oracle. I wouldn't bet my life on that one, but I've seen Oracle Drivers on my systems, and I've never installed any Oracle products.
I have some programming familiarity with Linux, but I've never done any database work on it, so I can't guide you there. If you are only using Linux, why don't you check the /bin and /lib subdirectories for those …
Joseph,
The best way to deal with a problem of this sort is to open and close the file twice, or reset the file pointer to the beginning after the 1st read.
The 1st time you read through the file you don't store anything. Its purpose is simply to find how much data is there.
After determining that you read it a second time but this time you only run the loop till you get to the end of the data - which you discovered in your 1st step.
In your case, since you are statically dimensioning an array with a max of 500 elements, if there are more data in the file than 500 you mustn't read beyond 500 or you'll corrupt your memory and likely crash fairly soon after that if not immediately.
I'm sure there is an implementation of ODBC for Unix. Its a database standard which applies to all the databases you listed. However, there are various levels of 'conformance' to the standard. That does not mean that some won't work with it, but rather that some optional features might not (most definitely aren't!) be implemented on all databases.
If you have Windows or access to it here is a little program that creates a Microsoft Access database ( a TestData.mdb file ), creates a Table1 in the database, writes a few records to the Table1, then dumps the data. If you have Microsoft Access you can open the database after the program runs. Its named TestData.mdb. It should be in whatever directory you are running the program from. Don't put this code in C:\Program Files or C:\Documents And Setting though. I don't believe it will work. At least not on XP. I'd recommend somewhere right off your C drive such as C:\OdbcDemo or C:\Code\OdbcDemo or something like that. This is a Microsoft thing I can't explain. Oh, one other thing. This program has to link to the two ODBC libraries, which in Visual Studio are ODBC32.lib and ODBCCP32.lib. With CodeBlocks or any of the GNU it will be libODBC32.a and libODBCCP32.a. This is important. It won't compile without static linking to those libs. I'll start posting the code now...
//Main.cpp
#include <windows.h>
#include <tchar.h>
#include <stdio.h>
#include <odbcinst.h>
#include <sql.h>
#include <sqlext.h>
#include "Strings.h"
#include "Sql.h"
#include "SqlProcs.h" …
I've been using ODBC for years. Its the very lowest level Api you can use. I'm pretty sure all other SQL Relational database access technologies are built on top of it. Perhaps ADO isn't; not sure of that.
Its platform independent. If you use it on Unix/Linux to access a database, and you would later want to access SQL Server or MS Access, there wouldn't probably be too much to change. For these reasons I'd highly recommend it. Far as I know Microsoft is still maintaining it; I think they have to.
Most newer folks don't like it because its procedural. No OOP. I've written very thin class wrappers around it that work very well for me. I have to admit I've never used it with anything other than Microsoft Access and SQL Server, plus some incidental use with Microsoft Excel. If you want my class wrapper to start with I'd be happy to post it. Actually, I'd like to see an example of a connection string for some of those databases you listed.
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.
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.
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().
I think Narue's idea is really good. I'd learn both. Old C books and tutorials in C are easy to find and inexpensive. Start 1 chapter at a time in each and you'll soon find that one reinforces the other.
Because today your luck is running good! All kidding aside, it just so happens that that address is still within your address space, so it isn't crashing. Add a few more lines of code and do it and your luck will likely run out! Doing that sort of thing will eventually lead to memory corruption, and believe me, those are the very, very, very worst kinds of problems to encounter. One time I lost three solid weeks due to something like that. What generally happens is that bizarre problems are encountered at some point later in the program due to corruption of your data segmentor something like that.
I spend about 50% to 60% of my time doing Windows CE and I just use the stdio.h functions for text output and I usually do the Api functions (CreateFile, SetFilePointer, etc.) for binary access. Here's an example of opening my DEBUG output file in one of my CE programs...
FILE* fp;
#if defined(MYDEBUG)
fp=_tfopen(_T("\\C_DRIVE\\Silvah\\Output.txt"),_T("w"));
_ftprintf(fp,_T("Output.txt Opened During fnWndProc_OnCreate()\n"));
_ftprintf(fp,_T("MYDEBUG Is Defined!\n"));
#endif
Just discovered there is a background color problem in the dialog. It didn't show up in Win 2000 which I developed the program on. Saw it in XP. I'll see if I can fix it tomorrow.
I reworked your code Cody to do without the resource script. Now there is only one file - Main.cpp. I did make quite a few changes; you should be able to recognize it as your program though; and this should work. Hope it helps.
#include <windows.h>
#define IDC_STATIC -1
#define ID_FILE_OPEN 1500
#define ID_FILE_SAVE 1505
#define ID_FILE_EXIT 1510
#define ID_OPTIONS 1600
#define IDD_ABOUT 1700
#define IDD_DIALOGABOUT 1700
#define IDD_GROUP 1705
#define IDD_OK 1710
#define IDD_CANCEL 1715
long __stdcall DlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch(msg)
{
case WM_CREATE:
EnableWindow(GetParent(hwnd),FALSE); //To make the popup dialog modal
return 0;
case WM_COMMAND:
switch(LOWORD(wParam))
{
case IDD_OK:
MessageBox(hwnd,"You Clicked The OK Button!","OK Button Click!",MB_OK);
SendMessage(hwnd,WM_CLOSE,0,0);
break;
case IDD_CANCEL:
MessageBox(hwnd,"You Clicked The Cancel Button!","Cancel Button Click!",MB_OK);
SendMessage(hwnd,WM_CLOSE,0,0);
break;
}
return 0;
case WM_CLOSE:
EnableWindow(GetParent(hwnd),TRUE); //To re-enable main window
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, msg, wParam, lParam);
}
long __stdcall WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
HINSTANCE hIns;
switch(msg)
{
case WM_CREATE:
{
char szClassName[]="Dialog";
HMENU hMenu, hSubMenu;
WNDCLASSEX wc;
hIns=((LPCREATESTRUCT)lParam)->hInstance;
hMenu = CreateMenu();
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu, MF_STRING, ID_FILE_OPEN, "&Open");
AppendMenu(hSubMenu, MF_STRING, ID_FILE_SAVE, "&Save");
AppendMenu(hSubMenu, MF_SEPARATOR, 0, 0 );
AppendMenu(hSubMenu, MF_STRING, ID_FILE_EXIT, "E&xit");
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&File");
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu, MF_STRING, ID_OPTIONS, "Explorer");
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Options");
hSubMenu = CreatePopupMenu();
AppendMenu(hSubMenu, MF_STRING, IDD_ABOUT, "&About");
AppendMenu(hMenu, MF_STRING | MF_POPUP, (UINT)hSubMenu, "&Help" );
SetMenu(hwnd, hMenu);
//Register Window Class For Dialog Box
wc.lpszClassName=szClassName, wc.lpfnWndProc=DlgProc;
wc.cbSize=sizeof(wc), wc.style=CS_HREDRAW | CS_VREDRAW;
wc.cbClsExtra=0, wc.cbWndExtra=0; …
I didn't knew the question was confusing. However some geniuses have decoded it correctly. Here I go again. Suppose I want to use bass.dll which have functions written in C, is there special thing i need to include or just give it a go?
Thanks for suggestions and link. I really learn here at DW
#include "bass.inc"
make sure bass.dll is somewhere in your dll search path. The same directory as your exe would work ok.
I'm inclined to think Cody might have a point about there being something wrong either with his Dev-Cpp install or something of that sort. He is continually having problems getting his programs to compile if they have resource scripts in them. And these same exact files are compiling with no problem for many of us here who try them- even when we use the Dev-C++ IDE.
For these reasons I'd be a bit surprised if a separate resource editor would make a difference. After all, all they do is auto-generate hopefully valid resource scripts, and the ones Cody already has ARE already valid resource scripts.
I've seen lots of anomolous behavior with the Dev-C++ setup already - especially regarding resource scripts.
Does anyone know the exact command line switches for compiling Cody's program from the command line using the gcc compiler installed with Dev-C++? I do command line compiling a pretty lot with MS compilers, and with gcc under Linux, but I've never done it with Windows gcc programs. If Cody would try that it might give a hint as to what his problems are.
I see alot of libraries written in C and I like C++ OOP way.
How can I use a given C library functions in C++?
I don't understand your question. All you need to do is include the header file and perhaps link with the library if its something unusual that isn't loaded by default. After all, C++ includes most of C.
For the most part, you can take any basic Win32 Sdk template type program usually associated with C style programming and rebuild the project in whatever development environment you are using as a C++ project; i.e., with .cpp extension instead of .c; and you automatically have the capability to do whatever OOP stuff you wish.
Essentially, that's how I program myself. A good deal of C++ I simply don't like; I have no use for it; I don't use it now; and have no intention of ever using it. I'm speaking most particularly of GUI class frameworks. However, there is a good bit of C++ that I do like so that's the part I use.
Perhaps an eclectic style, but it works for me. That's why your question confuses me. I must be misunderstanding your question because you surely know that.
Hi Cody!
I just tried the code posted by cikara21 and it worked perfectly including showing the 'About' dialog box. Somehow when I copied the code a few html tags showed up after the case about and I had to remove those. I used my Dev-C++ setup - 4.9.9.2 or something like that. Not sure if that's the newest or not. Is there a 5?
Dev-C++ is OK except the codetips infuriate me they are so intrusive. Maybe try CodeBlocks. I like that a lot. I also have VS2008 Pro but it cost me about $550. Like anything having to do with .NET its clunky and slow. It does produce generally small executables though. I believe CodeBlocks is only about a 20MB download. I'd guess that's doable from a dial up or otherwise slow connection.
I'll take a shot at it later when I have time Cody.
It seems to me you are letting yourself get overly hung up on these resource compiler/dialog issues. I'd move on to other stuff. Personally, I dislike everything to do with dialogs. I make very minimal use of them in my programs. There isn't hardly anything in Win32 programming that can't be done some other way than by using resource scripts and .rc files.
How create win32 application in Microsoft Visual Studio 2008 ??
I do not want to select " Empty project "
"Empty Project" is good. That's how I start all my VS projects. Of course, you have to know what to do next...
A Copy Constructor has to completely generate a new Person object with the Person object passed as a parameter. Apparently one of the members of this Person object is a pointer to a struct/class that probably looks something like this...
class Date
{
public:
void set_year(short year);
void set_month(short month);
void set_day(short day)
etc...
};
The newly created Person object can't use the memory allocations for the existing object passed as a parameter because if this later object gets destroyed/deleted/goes out of scope, the the new object will have bogus memory and will cause a crash. So every dynamically allocated member of the parameter class (the Person& parameter) will have to be duplicated by a memory allocation for the yet to be created object. That's what the 'new' is about. Then you'll have a completely independent object from the one passed in. So yes, you've answered your own question. It needs a new date memory block, otherwise, its sharing the other's, and won't be independent of it. Hope this helps.
I just recently posted some tutorials here...
http://www.jose.it-berater.org/smfforum/index.php?topic=3389.0
Lot of stuff having to do with pointers, message crackers, etc.
If you are into graphics at the Api level you should probably think about Charles Petzold's Programming Windows book. He is heavy into graphics. I can't really speak to other class framework wrappers on GDI or otherwise because I'm not into that.
AdRock,
Post some code in code tags. I don't think anybody wants to look at what you posted. Preferably short. Can you get a Hello, Woirld to compile in Linux?
Your declaration of destination only causes the compiler to allocate four bytes (32 bit OS) for the char* itself. In terms of memory at which it 'points', you need to allocate that with new, malloc, GlobalAlloc(), HeapAlloc(), whatever.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void strcpy2(const char* source, char* dest)
{
while (*source != 0)
{
*dest = *source;
dest++;
source++;
}
*dest = 0;
}
int main()
{
char* source = "Hello world";
char* destination=NULL;
destination=(char*)malloc(strlen(source)+1);
if(destination)
{
strcpy2(source, destination);
puts(source);
puts(destination);
free(destination);
system("pause");
}
return 0;
}
The other alternative is to declare an arbitrarily sized character array to serve as a buffer into which you can copy the string. If you absolutely know what the upper possible bound of what you are copying is, then its possible to do that. For example, if you knew the character string you were copying couldn't be over 63 characters, you could do this...
char szStringBuffer[64];
if(strlen(source)<64)
strcpy2(source, szStringBuffer);
else
puts("Buffer Not Big Enough!!!");
You havn't allocated any memory at destination into which you can copy what is at source, so you are corrupting your data segment.
Not really. The most useful and commonly used databases are known as 'relational databases' and the good thing about them is that they mostly follow the rules set down many years ago by all the big players in databases and those rules are ODBC. So, if you learn how to write a program that conncts to any particular one of these databases, then, chances are good that your program can switch to using another database with little or no modifications. For example, in my programming with Microsoft Access which I mentioned above, when I tested it with SQL Server, there were fairly minimal changes needing to be done to work wuth the latter. So what you need to do is get yourself some database to work with, learn a little SQL ( Structured Query Language ) , then see how you want to connect through C++ code if that's the way you want to go.
MS-Access is a great database for small projects. Its ok for 1-3 simultaneous connections. Anything more and Access can generate file corruptions.
Yea, that's the thing. I created our (my organization, i.e., where I work) main database about 5 years ago and it contains pretty many tables and lots of relationships. There are about 5 or 6 main users through my various front end programs; however, chances are small more than 2 or 3 would ever be performing transactions on it simultaneously. About two years ago another coder here added access to it through Asp.net for a particular type of database transaction that happens fairly infrequently - perhaps a couple per week. I consider this living dangerously; however, so far no problems.
I've mentioned many times that I thought we would be better served by mocving to Sql Server (we have several), but the way everybody looks at it is that if it ain't broke - don't fix it! Before I setup the Access database we had a miserable system we'd paid millions for which didn't hardly work and nobody understood. With Access everybody likes it and doesn't want to change. So we keep things pretty well backed up and hope for the best.
MS Access was my first experience with relational databases about 15 years ago. It always amazes me to see so many people knock it for one reason or another (its not free like MySql, its not as robust as Sql Server, on and on). I've had nothing but good experiences with it, and it serves as an excellent tool to get started learning about databases, structured query language, relationships in data, etc.
So the thing to do would be to get your tables and relationships set up, and once that's done then look into a user interface front end to the database. Heck, the various GUI tools in Access itself might be enough. However, if not, front ends can be coded in any number of languages. C++ probably isn't the best choice, but its certainly doable. Historically I believe, most folks used Visual Basic for database front ends. Its simply easier.
Hey Taphofyle!
You're into database programming with that. Unless you are a coding guru, I'd recommend not writing your own file structures, i.e., file access/retrieval, for something like that. If you haven't studied database programming yet, I'd recommend you do so. In C++ your choices are connecting with databases through higher level OOP front ends such as ADO (ActiveX Data Objects), or the lower level ODBC (Open DataBase Connectivity) route. I personally do all my database work through low level ODBC. I have some examples posted here...
http://www.jose.it-berater.org/smfforum/index.php?board=378.0
Both text (ascii or unicode) and binary data can be easily stored in either flat files you open, close & manage yourself, or in regular databases which would involve dealing with its Api, so the question doesn't really have anything to do with size. What does your data look like specifically, e.g., is it names and addresses, what?
Its not completely clear from your post whether you want to go the relational database route or the simple flat file route. That's basically the first question you must decide. The techniques involved vary considerable depending on which way you go.
It sounds to me Krisny that you've got to parse the file name apart returned from your directory obtaining function and insert the "\\" characters the compiler wants to see in the string you feed into ShellExecute(). Afterall, you said it works if you feed in a correctly specified path, i/e., "C:\\Dir1\\Dir2\\SomeProgram.exe". You are using MFC and have got a usable String class, No?
I put together a C++ version of the basic Inkey function. Its not exact. My intention was to make it exact, but I ran into some excrutiating problems. The Inkey$ function returns a dynamic basic string (allocated by the OLE String Engine). As such, it can contain null characters. I have my own string class, but it isn't based on Ole strings, but rather on Asciiz null terminated strings, and as such I can't embed nulls in the string. Therefore, I wasn't able to return a string from my string class that has a null as the first character, and the extended character code in the 2nd byte (cursor motion keys and so forth). So what I did was create a typedef like so...
typedef struct KEY
{
bool blnKeyPressed; //1 byte
bool blnExtended; //1 byte
char ch; //1 byte
char code; //1 byte
}KEY;
Here is my Inkey function which gets passed by reference a KEY struct...
void Inkey(KEY& k)
{
int ch;
memset(&k,0,4);
if(_kbhit())
{
ch=getch();
if(ch==0x00||ch==0xE0)
{
k.blnExtended=true, k.blnKeyPressed=true;
k.ch='\0', k.code=getch();
}
else
{
k.blnExtended=false, k.blnKeyPressed=true;
k.ch=(char)ch, k.code=(char)ch;
}
}
else
k.blnKeyPressed = false;
}
Here is a program that uses it...
//Main.cpp
#include <stdio.h>
#include <conio.h>
#include <string.h>
typedef struct KEY
{
bool blnKeyPressed; //1 byte
bool blnExtended; //1 byte
char ch; //1 byte
char code; //1 byte
}KEY;
void Inkey(KEY& k)
{
int ch;
memset(&k,0,4);
if(_kbhit())
{
ch=getch();
if(ch==0x00||ch==0xE0)
{
k.blnExtended=true, k.blnKeyPressed=true;
k.ch='\0', k.code=getch();
}
else
{
k.blnExtended=false, k.blnKeyPressed=true;
k.ch=(char)ch, k.code=(char)ch;
} …
Don't know if this will help, but these little fixes cause it to run in CodeBlocks without errors or warnings....
// ASCII-getche
#include <stdio.h>
#include <conio.h>
#include <iostream>
#include <string>
#include <stdlib.h>
using namespace std;
int main(void)
{
system ("color 0a");
int c=0;
char inp;
inp=' '; //Since you are saying inp is a char, give it a char
do
{
system("CLS");
cout << "\n\n\n\n\n\tThis program produces ASCII code for any key pressed.";
cout << "\n\n\n\n\n\tChar : " << inp << " ASCII: " << c <<"\n\n\n\tEsc to Exit,\tPresskey a key: ";
c = getche(); //* assign ASCII code to c
inp=c; // CHR$ from ASCII if extended, c=0
if(c==0)
{
c=getche();
inp=(char)NULL; //tell it to consider NULL a char, i.e., the NULL char
}
} while (c != 27); /* ESC to escape*/
cout << "\n\n\n\tBye\n\n\n";
getch();
}
Here's some additional info...
The MAKELONG macro creates an unsigned 32-bit value by concatenating two given
16-bit values.
DWORD MAKELONG
(
WORD wLow, // low-order word of long value
WORD wHigh // high-order word of long value
);
Parameters
wLow Specifies the low-order word of the new long value.
wHigh Specifies the high-order word of the new long value.
BN_CLICKED The BN_CLICKED notification message is sent when the user clicks a
button. The parent window of the button receives this notification
message through the WM_COMMAND message.
BN_CLICKED
idButton = (int) LOWORD(wParam); // identifier of button
hwndButton = (HWND) lParam; // handle to button
So you would need...
SendMessage(hParent, WM_COMMAND, MAKELONG(idButton, BN_CLICKED), hButton);
where hParent is the parent or container control of button in question and idButton
is the identifier of button from CreateWindow(). If you have either the hWnd of
button or control id you can get the other from either GetCtrlID() or GetDlgItem().
The parent of a control can be gotten from GetParent().
Also check out BN_CLICK message.
Sure, buttons are windows. In Windows, everything's a window except those things that aren't windows!
You could use SendMessage to the hWnd of the button with the BN_CLICKED notification - I believe - in the LOWRD of wParam. Please check out that part. There are macros to position various 16 bit quantities in either the low or hi word of wParam.
Yes, Seakayaker, you need another thread for that. I'll list all the code for a small program below that should show all the ingredients in a GUI example. The context for this particular program is that I wanted to add a button to one of my Windows CE data collector programs that when clicked would start a thread to collect Gps lats & longs every second for anywhere from 10 to 180 seconds. I didn't want this to interfere with the other data collection activities and so I wanted a 'worker' thread in the background running while the GUI was being used for other purposes.
The program below is VC++ 6 but should compile with anything. Save tyhe file as Main.cpp if you want. The program opens an output.txt log file that will help you see what is going on. When you click the button a thread is created and a Windows timer started that runs for ten seconds and places a message in the listbox every second.
#include <windows.h>
#include <stdio.h>
#include <time.h>
#define IDC_LISTBOX 2000
#define IDC_BUTTON 2005
FILE* fp;
typedef struct GPSDATA
{
double dblLatitude;
double dblLongitude;
}GpsData;
typedef struct WindowsEventArguments
{
HWND hWnd;
WPARAM wParam;
LPARAM lParam;
HINSTANCE hIns;
}WndEventArgs, *lpWndEventArgs;
void GetRawGps(double r_tic, double& dblLatitude, double& dblLongitude, double r_elv, double r_pdop, double r_ehe, double r_quality)
{
srand(time(NULL));
dblLatitude=rand();
dblLongitude=rand();
}
void __stdcall fnTimerProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
double dblLatitude=0.0,dblLongitude=0.0,r_tic=0.0,r_elv=0.0,r_pdop=0.0,r_ehe=0.0,r_quality=0.0;
unsigned int iNumReadingsDesired,iNum,iReturn=0;
CRITICAL_SECTION m_memLock;
GpsData* ptrGpsData=NULL;
char szBuffer[16];
HANDLE …
Sort of, the first one simply tells the system to request a repaint given those conditions. The UpdateWindow(hWnd); function on the other hand, allows you to request an update when you need one. If you make some changes to the window, where you don't change the size, then you will need to request a repaint yourself.
Exactly. In some types of scroll code, for example, when the user clicks the scroll bar up or down arrows, you may wish to entirely repaint the window to change what is displayed. A typical way of doing that would be to use the InvalidateRect() function followed by the UpdateWindow() function to force a WM_PAINT message. In the WM_PAINT processing different lines of text or whatever would be drawn.
I have Ivor Horton's VC++ 6 (around 2000 or so) "Beginning C++ 6" book. In that edition anyway there was one chapter devoted to Sdk style Windows programming. The rest of the book was all MFC.
If your only interest is to become acquainted with Sdk style coding for Windows then quickly move on to MFC or .NET (various class frameworks), then Ivor's book would be enough. However, if you wish to really delve deeper into programming Windows with the raw Api, then you need to acquire Charles Petzold's "Programming Windows" book.
Alright, so the first sends a request for the windows to be repainted whenever the width/height is edited by the user.
No, you've got the timing entirely wrong. Filling out the .style field of a WNDCLASSEX structure only occurs one time and that happens long before (in computer miliseconds) a window is created or becomes visible.
In contrast, an UpdateWindow() call can be made countless times during the execution of a running program. You need to grasp the concept of update regions possibly to fully understand this. A window can accumulate invalid regions without Windows automatically repainting it. To force an immediate WM_PAINT UpdateWindow can be used.
As I mentioned, you need to study a real solid three dimensional book with weight & mass to grasp all this.
These three items you mention refer to three distinct stages in the creation of a window using the low level Windows Api (the best way to program Windows in my opinion).
Before you can create a window you fill out all the fields of a WNDCLASSEX structure. This...
WindowClass.style = CS_HREDRAW | CS_VREDRAW;
pertains to the setting of one of the many fields (10 or so). It tells the operating system that when a window of the class szClassName is instantiated, and any change occurs to the window, the whole window should be redrawn (Windows will send a WM_PAINT message).
Note that the filling out of all the fields of a WNDCLASSEX structure is done before any windows of the class specified by the sz.ClassName field can be created/instantiated. In that sence, it represents the 1st step.
Once all the fields of the WNDCLASS striucture are filled out, one uses the RegisterClassEx() Api function to register the class with windows. the .szClassName field is of critical importance here. Let me digress for a moment.
Lets say I want to create an edit control (text box) with somewhat different characteristics than the standard/stock text box included with Windows. If I want to do that I create my own Window Class and fill out a WNDCLASSEX structure and specify the name of my new class/control through the .szClassName field. Lets say I call mine "MyEdit" . This would distinguish my edit control class from Windows own …
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.
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;
}