Click to See Complete Forum and Search --> : Cannot see the Window!


kajarigd
June 12th, 2009, 12:51 AM
Hi,
I have a program to display a window with two buttons. But, when I am executing the program I cannot see any window! But the .exe file continue to execute, and each time I have to go to the task manager to close it. The window is not showing, but the program is going to the default case in the switch(message). message is the command I am supposed to take from pressing a button.
Please help me!!
Thanks a lot!!

kajarigd
June 12th, 2009, 12:52 AM
THis is the main() code:

int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
CSerialCom testSerial;
testSerial.wcex.cbSize = sizeof(WNDCLASSEX); //<-----Needs to know the size of the structure
testSerial.wcex.style = CS_HREDRAW | CS_VREDRAW;//<-Window will redraw if resized
testSerial.wcex.lpfnWndProc = (WNDPROC)testSerial.WndProc;//<--------Messages will be sent to this procedure
testSerial.wcex.cbClsExtra = 0;//<-----------------------No extra bytes following class structure
testSerial.wcex.cbWndExtra = 0;//<-----------------------No extra bytes following instance
testSerial.wcex.hInstance = hInstance;//<---------------Handle to the instance that contains the window procedure.
testSerial.wcex.hIcon = LoadIcon(hInstance, IDI_APPLICATION);//<---Default application icon.
testSerial.wcex.hCursor = LoadCursor(NULL, IDC_ARROW);//<------------Standard arrow cursor
testSerial.wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW); //<----------------Gray back color for window
testSerial.wcex.lpszMenuName = NULL;//<-----------------------------------No Menu for this window
testSerial.wcex.lpszClassName = "RFIDCommunicationClass";//<-------Name of the class to be registered
testSerial.wcex.hIconSm = NULL;//-----------------------Find an appropriate small icon for us

//Class must be registered with the system before we can create the window
RegisterClassEx(&testSerial.wcex);

//-------------------- create a window-----------
//"RFIDCommunicationClass" - the name of the class we Registered
//"RFID Communication" - This will be the name of the window displayed in the title bar
//WS_OVERLAPPEDWINDOW is a window with a title bar and a border
//CW_USEDEFAULT - Use the default horizontal position for the window
//CW_USEDEFAULT - Use the default vertical position for the window
//CW_USEDEFAULT - Use the default width for the window
//CW_USEDEFAULT - Use the default height for the window
//NULL - This window has no parent
//NULL - This window has no menu
//hInstance - The application instance
//NULL - Add no extra data for the WM_CREATE message
testSerial.hWnd = CreateWindow("RFIDCommunicationClass", "RFID Communication", WS_TILED,CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);

//Now we will create two buttons to put on the form.
//These windows do not need to be registered with RegisterClass
//because they are predefined button classes.

//Button----------------Name of predefined class that creates a command button for us
//WS_CHILD--------------A flag that indicates these are to be children of a parent window
//290,30,90,30----------Left, right, width, and height of the buttons
//hWnd------------------The handle to the parent window

testSerial.Button1hWnd = CreateWindow("Button","Extreme VB",WS_CHILD, 290,30,90,30,testSerial.hWnd,NULL,hInstance,NULL);

testSerial.Button2hWnd = CreateWindow("Button","Exit",WS_CHILD, 380,30,90,30,testSerial.hWnd,NULL,hInstance,NULL);

ShowWindow(testSerial.hWnd, SW_SHOW);//<--------Lets show our main window
ShowWindow(testSerial.Button1hWnd, SW_SHOW);//<--Lets show button number 1
ShowWindow(testSerial.Button2hWnd, SW_SHOW);//<--Lets show button number 2

//This is the message pump that retrieve all
//message from the calling thread's message queue
while (GetMessage(&testSerial.msg, NULL, 0, 0))
{
DispatchMessage(&testSerial.msg);//Dispatches the message to our WndProc
}

return (int)testSerial.msg.wParam; //return exit code to the OS
}

cilu
June 12th, 2009, 03:02 AM
Is this all the code, or there is more? I don't see your win procedure. Do you have to do this with WinAPI? Can't you use MFC? It would be much easier.

kajarigd
June 12th, 2009, 03:13 AM
thanks for your reply! The other function I have is the WndProc(). I don't have any other functions for this. Here is it:

LRESULT CALLBACK CSerialCom::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LPVOID lpParam)
{

PAINTSTRUCT ps;//<---Structure needed for BeginPaint() and EndPaint()
HDC hdc;//<----------Handle to the display DC to be used for painting.
RECT rt;//<----------Structure use with GetClientRect() and DrawText()
CDC * dc;
CSerialCom *pObj = (CSerialCom *)lpParam;

char Title[] = "You found this tutorial at www.VisualBasicForums.com";

switch(message)//<----------Lets find out what message was sent
{
case WM_PAINT:
dc = pObj->BeginPaint(&ps);
hdc = *dc;//<---Prepare window for painting
pObj->GetClientRect(&rt);//<------Get coordinates of the window to draw on
DrawText(hdc,Title,(int)strlen(Title), &rt, DT_CENTER);//<--Draw some text
pObj->EndPaint(&ps);//<-----------Tel the OS we are done painting
break;
case WM_COMMAND://<-------Was one of our command buttons clicked?
//lParam = handle to control that fired this message
if((HWND)lParam == pObj->Button1hWnd)//<---Was it button number 1?
{
if(pObj->MessageBox("Do you want to visit the best site on the web?", "VisualBasicForum.com",MB_YESNO) == IDYES)
{
//Lets see whats going on over at exvb
ShellExecute(hWnd,"open","www.visualbasicforum.com",NULL,"C:\\", SW_SHOWNORMAL);
}
}
else //<----If it was not button 1 then it should be button number 2
{
if(pObj->MessageBox("Do you want to exit program","Quit",MB_YESNO) == IDYES)
{
pObj->DestroyWindow();//<---Sends a destroy message to the parent window
}
}
break;
case WM_DESTROY://<------User wants to quit so lets process this message
PostQuitMessage(0);//This will send GetMessage (in WinMain above) a zero and
//will exit that loop and quit our program
break;
default:
//Send unprocessed messages to the default windows procedure
pObj->MessageBox("You haven't pressed any button!!","Error",MB_OK+MB_ICONERROR);
//return pObj->DefWindowProc(message, wParam, lParam);

}
return 0;
}

ovidiucucu
June 12th, 2009, 04:16 AM
First of all, you have to
return DefWindowProc(hWnd, message, wParam, lParam);
for all not handled messages in window procedure ("default" switch branch).


[ Moved thread ]

kajarigd
June 12th, 2009, 04:21 AM
When I am enabling return DefWindowProc() in the default part of the switch, I am getting Application error while executing. It is saying, "The instruction at <addr> referenced memory at <addr>. The memory could not be read"

cilu
June 12th, 2009, 04:25 AM
I see CSerialComm has a member called BeginPaint(). That means it's derived (eventually) from CWnd. That means you're using MFC. So I don't understand why not building complete MFC application. :confused:

kajarigd
June 12th, 2009, 04:30 AM
I was actually following an online tutorial. I didn't realize it is using both API and MFC. Can you please suggest a MFC tutorial I can follow?
Thanks!

ovidiucucu
June 12th, 2009, 04:34 AM
I was actually following an online tutorial. I didn't realize it is using both API and MFC.

On the Internet there are few great things beside a lot of stupid ones.

Viorel
June 12th, 2009, 04:49 AM
Changing the last parameter of first CreateWindow could partially help:

CreateWindow(. . . ., (LPARAM)&testSerial);

kajarigd
June 12th, 2009, 04:54 AM
After changing it I am getting the following error:
'CreateWindowExA' : cannot convert parameter 12 from 'LPARAM' to 'LPVOID'

Also, return DefWindowProc() is giving me Application Error when I am executing the program.

Viorel
June 12th, 2009, 04:56 AM
After changing it I am getting the following error:
'CreateWindowExA' : cannot convert parameter 12 from 'LPARAM' to 'LPVOID'
[...]


Then try this:
CreateWindow(. . . ., (LPVOID)&testSerial);

kajarigd
June 12th, 2009, 05:00 AM
Thanks! I have changed it for all the three Creates. Now, it is compiling without errors. But I am still getting the "memory cannot be read" Application Error with the line: return DefWindowProc().

kajarigd
June 12th, 2009, 05:08 AM
This is my function: I had to declare the function static. For that I had to create CSerialCom *pObj = (CSerialCom *)lpParam; CSerialCom is the main class. I am not getting any any application error when I am commenting the line: return pObj->DefWindowProc(message, wParam, lParam);

LRESULT CALLBACK CSerialCom::WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam, LPVOID lpParam)

{

PAINTSTRUCT ps;//<---Structure needed for BeginPaint() and EndPaint()

HDC hdc;//<----------Handle to the display DC to be used for painting.

RECT rt;//<----------Structure use with GetClientRect() and DrawText()

CDC * dc;

CSerialCom *pObj = (CSerialCom *)lpParam;

char Title[] = "You found this tutorial at www.VisualBasicForums.com";

switch(message)//<----------Lets find out what message was sent

{

case WM_PAINT:

dc = pObj->BeginPaint(&ps);

hdc = *dc;//<---Prepare window for painting

pObj->GetClientRect(&rt);//<------Get coordinates of the window to draw on

DrawText(hdc,Title,(int)strlen(Title), &rt, DT_CENTER);//<--Draw some text

pObj->EndPaint(&ps);//<-----------Tel the OS we are done painting

break;

case WM_COMMAND://<-------Was one of our command buttons clicked?

//lParam = handle to control that fired this message

if((HWND)lParam == pObj->Button1hWnd)//<---Was it button number 1?

{

if(pObj->MessageBox("Do you want to visit the best site on the web?", "VisualBasicForum.com",MB_YESNO) == IDYES)

{

//Lets see whats going on over at exvb

ShellExecute(hWnd,"open","www.visualbasicforum.com",NULL,"C:\\", SW_SHOWNORMAL);

}

}

else //<----If it was not button 1 then it should be button number 2

{

if(pObj->MessageBox("Do you want to exit program","Quit",MB_YESNO) == IDYES)

{

pObj->DestroyWindow();//<---Sends a destroy message to the parent window

}

}

break;

case WM_DESTROY://<------User wants to quit so lets process this message

PostQuitMessage(0);//This will send GetMessage (in WinMain above) a zero and

//will exit that loop and quit our program

break;

default:

//Send unprocessed messages to the default windows procedure

//pObj->MessageBox("You haven't pressed any button!!","Error",MB_OK+MB_ICONERROR);

return pObj->DefWindowProc(message, wParam, lParam);

}

return 0;

}

Viorel
June 12th, 2009, 05:15 AM
I think that the CSerialCom::WndProc function should only have four parameters. Also confirm that it is static. Note that (CSerialCom*)lParam is only valid on WM_CREATE notification, therefore you should assign it to pObj only at this time; and keep pObj for the next messages; making it static is a simple solution.

ovidiucucu
June 12th, 2009, 05:26 AM
Beside that Viorel already stated.

Does CSerialCom::DefWindowProc something special?
I was suggested to directly call ::DefWindowProc Windows API function.
The CSerialCom class/structure, having all members public, only complicates the code, at least in your example.

kajarigd
June 12th, 2009, 05:34 AM
Thanks for all your quick replies! Yes. I have chaged WndProc to 4 params. It is compiling correctly. But, now I had to change the line "CSerialCom *pObj = (CSerialCom *)lpParam;" to "CSerialCom *pObj = (CSerialCom *)lParam;" as I am no longer using lpParam. Also, the WndProc method is declared static. After declaring static I was getting the errors that, BeginPaint(&ps) and other similar non-static functions cannot be accessed from a static function. For that I had to change it to pObj->BeginPaint(&ps).

But, I am still getting the same Application Error.

kajarigd
June 12th, 2009, 05:39 AM
I have kept the WinProc() function in the class CSerialCom(), and then wrote the WinMain() in main.cpp. I did this to keep the main.cpp short and simple. Is that a problem?

kajarigd
June 12th, 2009, 05:55 AM
Thanks for all your quick replies! Yes. I have chaged WndProc to 4 params. It is compiling correctly. But, now I had to change the line "CSerialCom *pObj = (CSerialCom *)lpParam;" to "CSerialCom *pObj = (CSerialCom *)lParam;" as I am no longer using lpParam. Also, the WndProc method is declared static. After declaring static I was getting the errors that, BeginPaint(&ps) and other similar non-static functions cannot be accessed from a static function. For that I had to change it to pObj->BeginPaint(&ps).

But, I am still getting the same Application Error.

I have kept the WinProc() function in the class CSerialCom(), and then wrote the WinMain() in main.cpp. I did this to keep the main.cpp short and simple. Is that a problem?

kajarigd
June 12th, 2009, 06:15 AM
When I am using the debugger to run the program I am getting the following error message:

An unhandled exception of type 'System.NullReferenceException' occurred in SerialCommTest.exe

Additional information: Object reference not set to an instance of an object.

Neandertal
June 18th, 2009, 04:53 PM
Change RegisterClassEx(&testSerial.wcex); to something like

if (!RegisterClassEx(&testSerial.wcex))
{
MessageBox(NULL, TEXT ("Can't register window class"), "Error", MB_ICONERROR);
return 0;
}


and see what happens. If the problem persists try removing buttons.

If you are trying to encapsulate wndproc and window itself in a class then you could use CreateWindowEx and put 'this' as a last arg to catch hwnd within wndproc and store it as class property or something similar.