|
Hey, cool. I did not know about this stuff, thank you *very* much.
Christian
After all, there's nothing wrong with an elite as long as I'm allowed to be part of it!! - Mike Burston Oct 23, 2001
Sonork ID 100.10002:MeanManOzI live in Bob's HungOut now
|
|
|
|
|
Hello fellow CPians. Happy New Year!
On my break from school, I thought I'd torture myself be reading Charles Petzold's Programming Windows. It's actually been a great read until now.
One of the sample programs declares a PMSG variable. The code goes on to allocate enough memory to store the appropriate amount of space using;
pmsg = malloc (cLinesMax * sizeof (MSG));
This code does not compile is VC6, SP5. I get the following error;
error C2440: '=' : cannot convert from 'void *' to 'struct tagMSG *'
Conversion from 'void*' to pointer to non-'void' requires an explicit cast
I've tried casting the return value to PMSG which solve the compile problem but the program bombs! I'm in way over my head on this one...
Any help that anyone can provide is greatly appreciated.
Sorry for the size of the post, but here's the complete code.
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
PSTR szCmdLine, int iCmdShow)
{
static TCHAR szAppName[] = TEXT("KeyView1");
HWND hwnd;
MSG msg;
WNDCLASS wndclass;
wndclass.style = CS_HREDRAW | CS_VREDRAW;
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.lpszMenuName = NULL;
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndclass.lpszClassName = szAppName;
if (!RegisterClass (&wndclass))
{
MessageBox(NULL, TEXT("This application requires WinNT to run."),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Keyboard Message Viewer #1"),
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT,
NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, iCmdShow);
UpdateWindow(hwnd);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT message,
WPARAM wParam, LPARAM lParam)
{
static int cxClientMax, cyClientMax;
static int cxClient, cyClient;
static int cxChar, cyChar;
static int cLinesMax, cLines;
static PMSG pmsg;
static RECT rectScroll;
static TCHAR szTop[] = TEXT("Message Key Char ")
TEXT(" Repeat Scan Ext ALT Prev Tran");
static TCHAR szUnd[] = TEXT("------- --- ---- ")
TEXT(" ------ ---- --- --- ---- ----");
static TCHAR* szFormat[2] = {
TEXT("%-13s %3d %-15s%c%6u %4d %3s %3s %4s %4s"),
TEXT("%-13s 0x%04x%1s%c %6u %4d %3s %3s %4s %4s") };
static TCHAR* szYes = TEXT("Yes");
static TCHAR* szNo = TEXT("No");
static TCHAR* szDown = TEXT("Down");
static TCHAR* szUp = TEXT("Up");
static TCHAR* szMessage[] = {TEXT("WM_KEYDOWN"), TEXT("WM_KEYUP"),
TEXT("WM_CHAR"), TEXT("WM_DEADCHAR"),
TEXT("WM_SYSKEYDOWN"), TEXT("WM_SYSKEYUP"),
TEXT("WM_SYSCHAR"), TEXT("WM_SYSDEADCHAR") };
HDC hdc;
int i, iType;
PAINTSTRUCT ps;
TCHAR szBuffer[128], szKeyName[32];
TEXTMETRIC tm;
switch (message)
{
case WM_CREATE:
case WM_DISPLAYCHANGE:
cxClientMax = GetSystemMetrics(SM_CXMAXIMIZED);
cyClientMax = GetSystemMetrics(SM_CYMAXIMIZED);
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hdc, &tm);
cxChar = tm.tmAveCharWidth;
cyChar = tm.tmHeight;
ReleaseDC(hwnd, hdc);
if (pmsg)
free (pmsg);
cLinesMax = cyClientMax / cyChar;
pmsg = malloc (cLinesMax * sizeof (MSG));
cLines = 0;
case WM_SIZE:
if (message == WM_SIZE)
{
cxClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
}
rectScroll.left = 0;
rectScroll.right = cxClient;
rectScroll.top = cyChar;
rectScroll.bottom = cyChar * (cyClient / cyChar);
InvalidateRect(hwnd, NULL, TRUE);
return 0;
case WM_KEYDOWN:
case WM_KEYUP:
case WM_CHAR:
case WM_DEADCHAR:
case WM_SYSKEYDOWN:
case WM_SYSKEYUP:
case WM_SYSCHAR:
case WM_SYSDEADCHAR:
for (i = cLinesMax - 1; i > 0; i--)
{
pmsg[i] = pmsg[i - 1];
}
pmsg[0].hwnd = hwnd;
pmsg[0].message = message;
pmsg[0].wParam = wParam;
pmsg[0].lParam = lParam;
cLines = min(cLines + 1, cLinesMax);
ScrollWindow(hwnd, 0, -cyChar, &rectScroll, &rectScroll);
break;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
SetBkMode(hdc, TRANSPARENT);
TextOut(hdc, 0, 0, szTop, lstrlen(szTop));
TextOut(hdc, 0, 10, szUnd, lstrlen(szUnd));
for (i = 0; i < min(cLines, cyClient / cyChar - 1); i++)
{
iType = pmsg[i].message == WM_CHAR ||
pmsg[i].message == WM_SYSCHAR ||
pmsg[i].message == WM_DEADCHAR ||
pmsg[i].message == WM_SYSDEADCHAR;
GetKeyNameText(pmsg[i].lParam, szKeyName, sizeof(szKeyName) / sizeof(TCHAR));
TextOut(hdc, 0, (cyClient / cyChar - 1 - i) * cyChar, szBuffer,
wsprintf(szBuffer, szFormat[iType],
szMessage[pmsg[i].message - WM_KEYFIRST],
(PSTR) (iType ? TEXT(" ") : szKeyName),
(TCHAR) (iType ? pmsg[i].wParam : ' '),
LOWORD (pmsg[i].lParam),
HIWORD (pmsg[i].lParam) & 0xFF,
0x10000000 & pmsg[i].lParam ? szYes : szNo,
0x20000000 & pmsg[i].lParam ? szYes : szNo,
0x40000000 & pmsg[i].lParam ? szDown : szUp,
0x80000000 & pmsg[i].lParam ? szUp : szDown));
}
EndPaint(hwnd, &ps);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
Paul Lyons
Do not go where the path may lead, go instead where there is no path and leave a trail.
- Ralph Waldo Emerson
|
|
|
|
|
I dunno what are you trying to say, man. I didn't read all the code, get bored.
But. The malloc() function returns void* , it is known and it is ok. You should cast the return value to whatever you want like this:
pmsg = (MSG*)malloc (cLinesMax * sizeof (MSG));
That's all. No buzzz It will elliminate the error you got
Philip Patrick
"Two beer or not two beer?" <shakesbeer>
Web-site: www.saintopatrick.com
|
|
|
|
|
malloc function returns void * type. You should make type casting if you want to use malloc. For example;
pmsg = (tagMSG*)malloc(cLinesMax * sizeof (MSG));
|
|
|
|
|
Oh my bad, lol, just read it all
What error you are getting?
Try to go in debugger step by step to see if your i is in boundaries. Also look on the pmsg array in debugger, i mean on all of its members, if they are initialized
Philip Patrick
"Two beer or not two beer?" <shakesbeer>
Web-site: www.saintopatrick.com
|
|
|
|
|
I'm creating an owner drawn menu derived from CMenu. Some of the menu items will be pop up menu items that have other menus pop up when you highlight them (of course). My owner drawn menu is going to custom draw an arrow signifying that it is a pop up menu, just like Windows does. The problem is that Windows still draws the original arrow on my menu items whenever it is a pop up item. Does anyone know how to remove this default drawing of pop up menu item arrows?
~Andrew Clark
|
|
|
|
|
Hi,
I am programming a multithreaded application however I am having lots of difficulties this week. I programmed many multithreaded applications but in this program I am really stucked. There is a main View class (say CMyView). This class have a CTaskManager class, which controls all the threads. The threads are called CTaskThread. Each CTaskThread need to call methods of CTaskManager. Here is the problematic part of the code:
class CTaskManager
{
public:
CTaskManager ();
virtual ~CTaskManager ();
protected:
CString m_sSharedVars [MAX_VARS];
...
};
void CTaskManager::ReplaceVariables (CString &str)
{
for (int i = 0 ; i < MAX_VARS ; i++)
{
if (m_sSharedVarNames [i] != m_sSharedVars [i])
{
while (str.Replace (m_sSharedVarNames [i], m_sSharedVars [i]) != 0);
}
}
}
When I run the program, it crashes at line m_sSharedVarNames [i] != m_sSharedVars [i] . In fact, it crashes whenever it tries to acces the elements of CTaskManager. However, when I remove the definition CString m_sSharedVars [MAX_VARS]; from the class and write it to the beginning of the CPP file (i.e. make it global), the program works fine. But the problem is that, I have to access other variables of CTaskManager, and I cannot make all of them global. The error message is the following:
<br />
The intruction at "0x5f47714c" referenced memeory at "0xcdcdcde1". The memory could not be "read". <br />
Click on OK to terminate the program<br />
Click on Cancel to debug the program<br />
When I click on Cancel and debug the program, it jumps to the following line in AFX.INL
<br />
_AFX_INLINE CString::operator LPCTSTR() const<br />
{ return m_pchData; }<br />
The error is
<br />
Unhandled exception in MyProgram.exe (MFC42D.DLL):0xC0000005:Access Violation<br />
Please HELP. I am stucked and I dont know what to do. I tried to use CCriticalSection to protect the data to be read/written by more than one threads at the same time but it didnt worked. In fact, when I run only one thread, the program crashes again!
Kind regards
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
I create the threads as follows (may help):
bool CTaskManager::LaunchTask (const CString &sTaskName, const CString &sTaskFolder)
{
CTaskObject *pTask = FindTask (sTaskName, sTaskFolder);
if (pTask)
{
if (pTask->m_bRunning)
return true;
pTask->m_bRunning = true;
CTaskThread *pThread = new CTaskThread ();
pThread->m_pTaskObject = pTask;
pThread->m_pTaskManager = this;
AddTaskThread (pThread);
pThread->CreateThread ();
return true;
}
else
return false;
return true;
}
Thanks for any helps.
Kind regards
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
1.Try init the m_sSharedVars[MAX_VARS] first before operations.
2.Or maybe an error occurs internally of CString in String-Length.
I Guess. I would try.
|
|
|
|
|
Your Code is not clear for uncertain fragments.Perhaps U know the meaning but I don't.Show more Definitions and Implementations for analysis.
|
|
|
|
|
What and where is m_sSharedVarNames[i] defined? It looks like something isn't being initialized. Try adding some debug statements or logging to see what's really happening and in what order.
Todd Smith
|
|
|
|
|
Sorry I forgot to show the definition of m_sSharedVarNames. m_sSharedVarNames is defined in the CPP file as a global variable.
CString m_sSharedVarNames [MAX_VARS] = {"<var1>", "<var2>", "<var3>", "<var4>", "<var5>",
"<var6>", "<var7>", "<var8>", "<var9>", "<var10>",
"<var11>","<var12>","<var13>","<var14>","<var15>",
"<var16>","<var17>","<var18>","<var19>","<var20>",
"<var21>","<var22>","<var23>","<var24>","<var25>"};
The problem occurs when I try to access the member variables of CTaskManager. Accessing sSharedVarNames (which is not a member of the class) is OK, but accessing sSharedVars (which is a public member of the class) is not. I dont know why this occurs.
Also, sSharedVars are initialized in the constructor.
Thanks for your helps. I am looking forward to hearing your suggestions.
Kind regards
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
0xCDCDCDCD is a dead giveaway of an uninitialized pointer - memory is set to that value right after it's allocated so you can catch just this sort of bug.
--Mike--
My really out-of-date homepage
Buffy's on. Gotta go, bye!
Sonork - 100.10414 AcidHelm
Big fan of Alyson Hannigan.
|
|
|
|
|
Michael Dunn wrote:
0xCDCDCDCD is a dead giveaway of an uninitialized pointer - memory is set to that value right after it's allocated so you can catch just this sort of bug.
Hi Mike,
That helped a lot. I found that the error is not related to the threads but an uninitizlized variable. In fact, the variable is initialized, but after sometime it somehow becomes invalid. The source code is very long and now I am trying to find the code fragment that changes that pointer.
Anyway, THANKS A LOT FOR YOUR HELPS.
Happy new year all CP fellows.
GOD BLESS CP
Kind regards
Mustafa Demirhan
http://www.macroangel.com
Sonork ID 100.9935:zoltrix
|
|
|
|
|
Would the Programs made by old ver VC++(MFC) run well under .NET or WINxp ??
Otherwise programs made by Visual.NET(C#) run well under old ver WIN ??
RainForest
Northern Jiaotong University CHINA
|
|
|
|
|
The backward compatibility is exists in all versions of Windows. If you made a program with VS 6.0, you can run it in XP. Not sure about opening 6.0 projects with .NET, but think it can be done.
The second, if you have a program done on C# and compiled with .NET, you can run it on prior Windows versions only if it has a Components Upgrade installed, like Service Pack.
That is what I read, but never tried. You can just make a test and tell us
Philip Patrick
"Two beer or not two beer?" <shakesbeer>
Web-site: www.saintopatrick.com
|
|
|
|
|
"Opening VS6.0 projects with .NET",Is everything here goes all right,you know,I mean the IL of .NET framework would cause problems while opening VS6.0 projects.Or U mean that there is a transformation occurs.The VS6 CODE would be changed into IL compatible style.
|
|
|
|
|
Yep, I meant transformation, like when you are opening a VC5 project from VC6. But as I said, I'm not sure of this aspect at all. I don't have .NET installed and still don't want to do it It is too fresh
Philip Patrick
"Two beer or not two beer?" <shakesbeer>
Web-site: www.saintopatrick.com
|
|
|
|
|
Hi, All!!!
=======
I saw this in the MSDN
<code>0 </code>through<code> WM_USER – 1</code> Messages reserved for use by the system.
<code>WM_USER </code>through<code> 0x7FFF</code> Integer messages for use by private window classes.
<code>WM_APP </code>through<code> 0xBFFF</code> Messages available for use by applications.
<code>0xC000 </code>through<code> 0xFFFF</code> String messages for use by applications.
<code>Greater </code>than<code> 0xFFFF</code> Reserved by the system for future use.
What is the difference between WM_USER and WM_APP ?
and, Why do I need to RegisterWindowMessage ?
Yours truly. . .
|
|
|
|
|
You should read it all There is a description of what is that. But I copy-pasted it for you here:
Message numbers in the second range (WM_USER through 0x7FFF) can be defined and used by an application to send messages within a private window class. These values cannot be used to define messages that are meaningful throughout an application, because some predefined window classes already define values in this range. For example, predefined control classes such as BUTTON, EDIT, LISTBOX, and COMBOBOX may use these values. Messages in this range should not be sent to other applications unless the applications have been designed to exchange messages and to attach the same meaning to the message numbers.
Message numbers in the third range (0x8000 through 0xBFFF) (WM_APP+) are available for application to use as private messages. Message in this range do not conflict with system messages.
And RegisterWindowMessage is needed to... register a message on single computer so you will be sure that no one will use the same number on that puter
Philip Patrick
"Two beer or not two beer?" <shakesbeer>
Web-site: www.saintopatrick.com
|
|
|
|
|
Why do I need to RegisterWindowMessage ???
Q1 : Can't I just use WM_APP + ... Intead of the RegisterWindowMessage thing?
Q2 : Do I need to RegisterWindowMessage every time I run the app? or just in the 1st time ?
Thanks
|
|
|
|
|
Well...
A1: Yes, you can just use WM_APP+.. but.. imagine that you defined WM_APP+2 message ID and some other running program defined same message. And doesn't matter that YOU are sending your message to particular HWND, but the other prog. is sending using broadcast, that means you will get 2 messages, yours and not. That's why you need RegisterWindowMessage .
But... You have to use Register... only if you jave TWO applications, that communicating with each other. Within ONE application (when you are sending messages to CHILD and not top-level windows) you can simply define the message id.
A2: Yes you have to register your message everytime the application starts. See a simple example below:
UINT WM_MYCUSTOM_MESSAGE = RegisterWindowMessage(_T("WM_MYCUSTOM_MESSAGE"));
Of course instead of WM_MYCUSTOM_MESSAGE you can use any name you can imagine. Once the message is registered, you can get its value in another application with exactly same string of code.
This is the main idea
Philip Patrick
"Two beer or not two beer?" <shakesbeer>
Web-site: www.saintopatrick.com
|
|
|
|
|
|
Hmm... there is no connection between MFC and Window Messages. You can still use MFC and send messages between windows...
Philip Patrick
"Two beer or not two beer?" <shakesbeer>
Web-site: www.saintopatrick.com
|
|
|
|
|
Philip Patrick wrote:
Hmm... there is no connection between MFC and Window Messages. You can still use MFC and send messages between windows...
Isn't that an oxymoron?
|
|
|
|
|