|
Thank you very much for your help.
MZakarni
|
|
|
|
|
I've been injured my eyes trying to find the logical bug (since it is
not syntax or any other error that could VC report), so I'm asking you
if you could help me to find the bug.
Program is retyped from book and unfortunately and don't have the
original source code to compare it with.
Program should create main window and in it the other four child
windows and do some display in each of them except the main window.
But when I try to run the program, it only display the main window and
the client area, without child windows in it!
Just to say one more time, VC does not report any error or warning, so
it must be the logical bug in code.
Here's the source (I apologize for text length in mail):
#include <windows.h><br />
#include <math.h><br />
<br />
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam);<br />
<br />
int cyChar;<br />
<br />
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, <br />
PSTR szCmdLine, int iCmdShow)<br />
{<br />
static TCHAR szAppName[] = TEXT("Multi1");<br />
HWND hwnd;<br />
MSG msg;<br />
WNDCLASS wc;<br />
<br />
wc.style = CS_HREDRAW | CS_VREDRAW;<br />
wc.lpfnWndProc = WndProc;<br />
wc.cbClsExtra = 0;<br />
wc.cbWndExtra = 0;<br />
wc.hInstance = hInstance;<br />
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION);<br />
wc.hCursor = LoadCursor(NULL, IDC_ARROW);<br />
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);<br />
wc.lpszMenuName = NULL;<br />
wc.lpszClassName = szAppName;<br />
<br />
if (!RegisterClass(&wc))<br />
{<br />
MessageBox(NULL, TEXT("This Program Requires Windows NT!"),<br />
szAppName, MB_ICONERROR);<br />
return 0;<br />
}<br />
<br />
hwnd = CreateWindow(szAppName, TEXT("Multitasking Demo"),<br />
WS_OVERLAPPEDWINDOW,<br />
CW_USEDEFAULT, CW_USEDEFAULT,<br />
CW_USEDEFAULT, CW_USEDEFAULT,<br />
NULL, NULL, hInstance, NULL);<br />
<br />
ShowWindow(hwnd, iCmdShow);<br />
UpdateWindow(hwnd);<br />
<br />
while (GetMessage(&msg, NULL, 0, 0))<br />
{<br />
TranslateMessage(&msg);<br />
DispatchMessage(&msg);<br />
}<br />
return msg.wParam;<br />
}<br />
<br />
int CheckBottom(HWND hwnd, int cyClient, int iLine)<br />
{<br />
if (iLine * cyChar + cyChar > cyClient)<br />
{<br />
InvalidateRect(hwnd, NULL, TRUE);<br />
UpdateWindow(hwnd);<br />
iLine = 0;<br />
}<br />
return iLine;<br />
}<br />
<br />
<br />
LRESULT APIENTRY WndProc1(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)<br />
{<br />
static int iNum, iLine, cyClient;<br />
HDC hdc;<br />
TCHAR szBuffer[16];<br />
<br />
switch (message)<br />
{<br />
case WM_SIZE:<br />
cyClient = HIWORD(lParam);<br />
return 0;<br />
<br />
case WM_TIMER:<br />
if (iNum < 0)<br />
iNum = 0;<br />
<br />
iLine = CheckBottom(hwnd, cyClient, iLine);<br />
hdc = GetDC(hwnd);<br />
<br />
TextOut(hdc, 0, iLine * cyChar, szBuffer,<br />
wsprintf(szBuffer, TEXT("%d"), iNum++));<br />
<br />
ReleaseDC(hwnd, hdc);<br />
iLine++;<br />
return 0;<br />
}<br />
return DefWindowProc(hwnd, message, wParam, lParam);<br />
}<br />
<br />
<br />
LRESULT APIENTRY WndProc2(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)<br />
{<br />
static int iNum = 1, iLine, cyClient;<br />
HDC hdc;<br />
int i, iSqrt;<br />
TCHAR szBuffer[16];<br />
<br />
switch (message)<br />
{<br />
case WM_SIZE:<br />
cyClient = HIWORD(lParam);<br />
return 0;<br />
<br />
case WM_TIMER:<br />
do<br />
{<br />
if (++iNum < 0)<br />
iNum = 0;<br />
<br />
iSqrt = (int) sqrt(iNum);<br />
for (i = 2; i <= iSqrt; i++)<br />
if (iNum % i == 0)<br />
break;<br />
}<br />
while (i <= iSqrt);<br />
<br />
iLine = CheckBottom(hwnd, cyClient, iLine);<br />
hdc = GetDC(hwnd);<br />
<br />
TextOut(hdc, 0, iLine * cyChar, szBuffer,<br />
wsprintf(szBuffer, TEXT("%d"), iNum));<br />
<br />
ReleaseDC(hwnd, hdc);<br />
iLine++;<br />
return 0;<br />
}<br />
return DefWindowProc(hwnd, message, wParam, lParam);<br />
}<br />
<br />
<br />
LRESULT APIENTRY WndProc3(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)<br />
{<br />
static int iNum = 0, iNext = 1, iLine, cyClient;<br />
HDC hdc;<br />
int iTemp;<br />
TCHAR szBuffer[16];<br />
<br />
switch (message)<br />
{<br />
case WM_SIZE:<br />
cyClient = HIWORD(lParam);<br />
return 0;<br />
<br />
case WM_TIMER:<br />
if (iNum < 0)<br />
{<br />
iNum = 0;<br />
iNext = 1;<br />
}<br />
<br />
iLine = CheckBottom(hwnd, cyClient, iLine);<br />
hdc = GetDC(hwnd);<br />
<br />
TextOut(hdc, 0, iLine * cyChar, szBuffer,<br />
wsprintf(szBuffer, TEXT("%d"), iNum));<br />
<br />
ReleaseDC(hwnd, hdc);<br />
iTemp = iNum;<br />
iNum = iNext;<br />
iNext += iTemp;<br />
iLine++;<br />
return 0;<br />
}<br />
return DefWindowProc(hwnd, message, wParam, lParam);<br />
}<br />
<br />
<br />
LRESULT APIENTRY WndProc4(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)<br />
{<br />
static int cxClient, cyClient;<br />
HDC hdc;<br />
int iDiameter;<br />
<br />
switch (message)<br />
{<br />
case WM_SIZE:<br />
cxClient = LOWORD(lParam);<br />
cyClient = HIWORD(lParam);<br />
return 0;<br />
<br />
case WM_TIMER:<br />
InvalidateRect(hwnd, NULL, TRUE);<br />
UpdateWindow(hwnd);<br />
<br />
iDiameter = rand() % (max(1, min(cxClient, cyClient)));<br />
hdc = GetDC(hwnd);<br />
<br />
Ellipse(hdc, (cxClient - iDiameter) / 2,<br />
(cyClient - iDiameter) / 2,<br />
(cxClient + iDiameter) / 2,<br />
(cyClient + iDiameter) / 2);<br />
<br />
ReleaseDC(hwnd, hdc);<br />
return 0;<br />
}<br />
return DefWindowProc(hwnd, message, wParam, lParam);<br />
}<br />
<br />
<br />
LRESULT APIENTRY WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)<br />
{<br />
static HWND hwndChild[4];<br />
static TCHAR* szChildClass[] = { TEXT("Child1"), TEXT("Child2"),<br />
<br />
TEXT("Child3"),<br />
TEXT("Child4") };<br />
static WNDPROC ChildProc[] = { WndProc1, WndProc2, WndProc3, WndProc4 };<br />
HINSTANCE hInstance;<br />
int i, cxClient, cyClient;<br />
WNDCLASS wc;<br />
<br />
switch (message)<br />
{<br />
case WM_CREATE:<br />
hInstance = (HINSTANCE) GetWindowLong(hwnd, GWL_HINSTANCE);<br />
<br />
wc.style = CS_HREDRAW | CS_VREDRAW;<br />
wc.cbClsExtra = 0;<br />
wc.cbWndExtra = 0;<br />
wc.hInstance = hInstance;<br />
wc.hIcon = NULL;<br />
wc.hCursor = LoadCursor(NULL, IDC_ARROW);<br />
wc.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);<br />
wc.lpszMenuName = NULL;<br />
<br />
for (i = 0; i < 4; i++)<br />
{<br />
wc.lpfnWndProc = ChildProc[i];<br />
wc.lpszClassName = szChildClass[i];<br />
<br />
RegisterClass(&wc);<br />
<br />
hwndChild[i] = CreateWindow(szChildClass[i], NULL,<br />
<br />
WS_CHILDWINDOW |<br />
WS_BORDER | WS_VISIBLE,<br />
<br />
0, 0, 0, 0,<br />
<br />
hwnd, (HMENU) i,<br />
hInstance, NULL);<br />
}<br />
<br />
cyChar = HIWORD(GetDialogBaseUnits());<br />
SetTimer(hwnd, 1, 10, NULL);<br />
return 0;<br />
<br />
case WM_SIZE:<br />
cxClient = LOWORD(lParam);<br />
cyClient = HIWORD(lParam);<br />
<br />
for (i = 0; i < 4; i++);<br />
MoveWindow(hwndChild[i], (i % 2) * cxClient / 2,<br />
<br />
(i > 1) * cyClient / 2,<br />
<br />
cxClient / 2, cyClient / 2,<br />
TRUE);<br />
return 0;<br />
<br />
case WM_TIMER:<br />
for (i = 0; i < 4; i++)<br />
SendMessage(hwndChild[i], WM_TIMER, wParam, lParam);<br />
return 0;<br />
<br />
case WM_CHAR:<br />
if (wParam == '\x1B')<br />
DestroyWindow(hwnd);<br />
return 0;<br />
<br />
case WM_DESTROY:<br />
KillTimer(hwnd, 1);<br />
PostQuitMessage(0);<br />
return 0;<br />
}<br />
return DefWindowProc(hwnd, message, wParam, lParam);<br />
}
Help in any form is welcome
Thanks
|
|
|
|
|
In WndProc 's body you must:
<br />
case WM_SIZE:<br />
cxClient = LOWORD(lParam);<br />
cyClient = HIWORD(lParam);<br />
<br />
for (i = 0; i < 4; i++)<font color="blue">
MoveWindow(hwndChild[i], (i % 2) * cxClient / 2,<br />
<br />
(i > 1) * cyClient / 2,<br />
<br />
cxClient / 2, cyClient / 2,<br />
<br />
<br />
Should be enough...
rechi
|
|
|
|
|
I CAN NOT BELIEVE I MADE SUCH MISTAKE !!!
Thanks Bogdan.
|
|
|
|
|
Hello, all
Can anyone tell is a message cannot be peeked in a thread? for example:
Program 1:
LRESULT OnOK(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
MSG msg;
unsigned int nTimerID = SetTimer(hWnd, 1, 2000, 0);
while(1)
{
if( PeekMessage(&msg, hWnd, WM_TIMER, WM_TIMER, PM_REMOVE) )
{
MessageBox(hWnd, "Timer out", NULL, 0);
break;
}
}
KillTimer(hWnd, nTimerID);
}
Program 1 has no problem, the WM_TIMER message can be successfully peeked by PeekMessage. but please take a look at program 2.
Program 2:
LRESULT OnOK(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
unsigned long nThreadID = 0;
HANDLE hThread = CreateThread(NULL, 0, ThreadProc, (void*)&hWnd, 0, &nThreadID);
WaitForSingleObject(hThread, INFINITE);
return 0;
}
unsigned long WINAPI ThreadProc(LPVOID pvParam)
{
HWND* phWnd = (HWND*)pvParam;
HWND hWnd = *phWnd;
MSG msg;
unsigned int nTimerID = SetTimer(hWnd, 1, 2000, 0);
while(1)
{
if( PeekMessage(&msg, hWnd, WM_TIMER, WM_TIMER, PM_REMOVE) )
{
MessageBox(hWnd, "Time out", NULL, 0);
break;
}
}
KillTimer(hWnd, nTimerID);
return 0;
}
I run program 2 in debug mode, i found the timer is successfully created, but there just no WM_TIMER message. Later i changed the "WaitForSingleObject"(in OnOK function) into "MsgWaitForMultipleObjects", i found the WM_TIMER again, but it is returned by "MsgWaitForMultiObjects", not in the thread function.
I'm confused now, can anyone tell me how to peek a message in a thread?
|
|
|
|
|
From the PeekMessage docs:
<quote>
PeekMessage retrieves only messages associated with the window identified by the hWnd parameter or any of its children as specified by the IsChild function, and within the range of message values given by the wMsgFilterMin and wMsgFilterMax parameters. If hWnd is NULL, PeekMessage retrieves messages for any window that belongs to the current thread making the call. (PeekMessage does not retrieve messages for windows that belong to other threads.) If hWnd is –1, PeekMessage only returns messages with a hWnd value of NULL, as posted by the PostThreadMessage function. If wMsgFilterMin and wMsgFilterMax are both zero, PeekMessage returns all available messages (that is, no range filtering is performed).
They key point here is: "(PeekMessage does not retrieve messages for windows that belong to other threads.)" which I assume is the case here.
Why do you want to use a Timer in a thread anyway. You should either put the thread to sleep waiting for an event to wake it up, or if you have to then use Sleep() to temporarilly suspend it.
Neville Franks, Author of ED for Windows. www.getsoft.com
|
|
|
|
|
Thanks Franks.
The main purpose of doing this by this way is i want to wait another message comes in, just like:
unsigned long ThreadProc(LPVOID pvParam)
{
MSG msg;
SetTimer(...);
while(1)
{
if( PeekMessage(&msg, hWnd, WM_SOCKET_MESSAGE, WM_SOCKET_MESSAGE, PM_REMOVE)
{
// Receive the data from the socket
// ...
// if (it's the last part of the data)
// break;
// else
// Reset the timer
// bSuccess = TRUE;
}
if( PeekMessage(&msg, hWnd, WM_TIMER, WM_TIMER, PM_REMOVE)
{
// Time is up
bSuccess = FALSE;
break;
}
}
KillTimer(...);
if( bSuccess )
return nLengthOfTheDataReceive;
else
return -1; //Error
}
Do you have a better way of doing this?
|
|
|
|
|
You could use clock().
eg. Before the while loop: clock_t StartTime = clock();
Then in the loop: if ( ( clock() - StartTime ) > MaxWait ) ...
It would be better still if the worker thread didn't have to waist time and CPU cycles in this loop though. Typically worker threads use WaitForxxx for some event to occur, do whatever processing is required, and then either exit or return to the WaitForxxx function.
You might want to look at some of the socket articles here at CP and see how they handle whatever you are trying to do.
Neville Franks, Author of ED for Windows. www.getsoft.com
|
|
|
|
|
i considered this way, but i feel it's very un-effecient(nor the TIMER-Way), cos the CPU use all its time to check whether the time is over, but it can't determin which thread is more useful, every thread is treated equally.
do you think sleep() will be better? or another way?
|
|
|
|
|
Hello,
My program allows users print photos. How do I handle if they want to
print the same photo more than one copies? Do I really have to do StartPage
and EndPage for 100 times if they want 100 copies?
Thanks,
Hiu Sing Ngai
|
|
|
|
|
Hiusing wrote:
Do I really have to do StartPage
and EndPage for 100 times if they want 100 copies?
AFAIK, no. Have a look at the DEVMODE struct. It has a dmCopies member.
You can fill such a struct with a call to DocumentProperties, modify that single member, and set it back using another call to DocumentProperties. Please make sure the printer driver indeed handles multiple copies by checking the DM_COPIES flag in dmFields.
|
|
|
|
|
How do you get the red, green, and blue out of a COLORREF variable?
There's always one more bug.
|
|
|
|
|
Use GetRValue, GetBValue and GetGValue macros.
regards
|
|
|
|
|
Thanks a lot
There's always one more bug.
|
|
|
|
|
I got a lil problem here. I have several projects built with Visual Studio 6. Recently switched to Visual Studio.NET and found that it compiles/linkages all projects using MFC7 dlls. Of course it is not working on OS that doesn't have .NET framework installed. And this is not a good point. So my question is: is it still possible to use MFC6 in Visual Studio .NET and how to do that?
I even created a simple Test application with MFC, and tried it on Windows 98... "Get me MFC7 now!" it said
I hope there is some way to do that, otherwise I'll have to bring the VS.NET back to store, no use of it then
Philip Patrick
Web-site: www.stpworks.com
"Two beer or not two beer?" Shakesbeer
|
|
|
|
|
MFC 7 works perfectly fine without the .NET runtime installed...
- Anders
Money talks, but all mine ever says is "Goodbye!"
|
|
|
|
|
Philip Patrick wrote:
is it still possible to use MFC6 in Visual Studio .NET
No, VS.NET comes with MFC 7 and that's what it uses. I'm an advocate of linking MFC and CRT statically so you never have to worry about the MFC DLLs. MFC7 does not use or require the .NET framework.
--Mike--
Just released - RightClick-Encrypt v1.4 - Adds fast & easy file encryption to Explorer
My really out-of-date homepage
Sonork-100.19012 Acid_Helm
|
|
|
|
|
Michael Dunn wrote:
I'm an advocate of linking MFC and CRT statically so you never have to worry about the MFC DLLs.
But doesn't it eat up all your memory if you have more than one of this kind of programs?
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
<nobr>They say I'm lazy but it takes all my time
|
|
|
|
|
You're blowing things way out of proportion. It doesn't use "all" your memory. Each executable image will be larger, however that is preferable to having to debug screwy problems caused by different DLL versions, which will appear to be your fault because, hey, your program is crashing.
--Mike--
Just released - RightClick-Encrypt v1.4 - Adds fast & easy file encryption to Explorer
My really out-of-date homepage
Sonork-100.19012 Acid_Helm
|
|
|
|
|
Michael Dunn wrote:
You're blowing things way out of proportion.
Hehe. Ok. Sorry for that
Michael Dunn wrote:
that is preferable to having to debug screwy problems caused by different DLL versions, which will appear to be your fault because, hey, your program is crashing.
Sure, but there is always a trade-off
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
<nobr>They say I'm lazy but it takes all my time
|
|
|
|
|
.NET framework is not needed. You need to distribute MFC7 dll files with your app.
See informations about redistributable files in MSDN.
Pavel
Sonork 100.15206
|
|
|
|
|
Yeah, thanx. Looked around, read some MSDN help that comes with VS.NET... Well redistributing MFC7 is better than the whole .NET framework, although it takes like 4Mb *sighs*
Philip Patrick
Web-site: www.stpworks.com
"Two beer or not two beer?" Shakesbeer
|
|
|
|
|
Philip Patrick wrote:
thanx
My pleasure.
Philip Patrick wrote:
Well redistributing MFC7 is better than the whole .NET framework
MFC libraries have nothing in common with .NET Framework except that MFC7 is part of VS.NET studio. MFC is classic unmanaged C++ library. .NET is from another world.
Pavel
Sonork 100.15206
|
|
|
|
|
I have not used VC7 yet. If the .NET framework is not required for programs written with VC7, then what is .NET framework for?
|
|
|
|
|
You can write programs of two kinds using VC++ 7, unmanaged and managed. Unmanaged programs are using WIN32 API and optionally some libraries like MFC or ATL, nothing from .NET, it's the same programming as in previous versions with new IDE and some new features in libraries and compiler. Managed ones are interfacing with .NET framework using MS specific language extensions. .NET framework is an environment very similar to Java with bytecode(called MSIL here), garbage collector, objects and interfaces, rich libraries, see this[^].
Pavel
Sonork 100.15206
|
|
|
|
|