|
I think you get it now. When you call GetBuffer(), you get access to the char buffer and you can modify it however you want (as long as you don't overrun the end of the buffer). Calling ReleaseBuffer() means you no longer need this direct access, and the CString object once again becomes responsible for managing the memory associated with the buffer.
--Mike--
http://home.inreach.com/mdunn/
The preferred snack of 4 out of 5 Lounge readers.
|
|
|
|
|
Thanks for the help - all this WTL stuff, combined with trying to read/write ID3 tags, I got a little sidetracked and didn't bother checking out some of the basics. You know what they say - when you make an assumption, you make an ass out of u and umption. ( yeah, it doesn't work, but it's from one of my favourite movies, so I'll quote it anyhow )
Thanks again
Christian
The content of this post is not necessarily the opinion of my yadda yadda yadda.
To understand recursion, we must first understand recursion.
|
|
|
|
|
Hey all. I'm using GlobalAlloc to allocate memory for a structure. One member of that structure is a 'char *'. I'm using 'malloc' to allocate memory for the string. My question is does GlobalFree free my string, or just the HGLOBAL returned by GlobalAlloc? Or put another way, do I have to call free(m_MyString) before calling GlobalFree?
Thanks in advance for any help.
Jamie Nordmeyer
Portland, Oregon, USA
|
|
|
|
|
Well, yes - you should call free() - GlobalFree() won't know about your char*.
Interesting stuff. malloc on 32 bit systems uses HeapAlloc, I think - the GlobalAlloc / LocalAlloc stuff is 16 bit. The new functions (HeapAlloc et al) can do more in terms of actually creating/managing heaps.
How have you come to use GlobalAlloc?
|
|
|
|
|
Hi Tim. Thanks for the reply. I'm trying to write my own window class. Why? One, so I don't have to link to MFC, and two, so I can study how Windows works from the ground level (using API calls and such). I'm using GlobalAlloc to create a pointer to my window classes 'this' pointer for use in its WndProc. I'd never really tried anything like this before, so when I first noticed GlobalAlloc, it looked like what I needed.
I'll use HeapAlloc instead, since it's 32-bit, and go from there!
Jamie Nordmeyer
Portland, Oregon, USA
|
|
|
|
|
Visual C++ 6.0, sp5
NT4, sp5
(I also posted this on the ADO board)
I'm working on an app that uses ADO to access an oracle database. The following code is part of the function that opens a recordset (try/catch stuff removed for the sake of brevity):
Fields* m_pFields = NULL;
SAFE_CALL(m_piRecordSet->Open(vSQL, vConnection, adOpenDynamic, adLockOptimistic, adCmdText));
int m_nRecordCount = m_piRecordSet->GetRecordCount();
SAFE_CALL(m_piRecordSet->get_Fields(&m_pFields));
...and this is a code snippet from the function we use to close the recordset:
if (m_pFields)
{
m_pFields->Release();
}
SAFE_CALL(m_piRecordSet->Close());
m_piRecordSet.Release();
m_piRecordSet = NULL;
The problem is with the m_pFields variable.
The first 10 or so times we call the function containing this code, it's a valid pointer. On or about the nth time, the variable is NULL. Actually "not initialized" would be a better description of it's state, because if we don't set it to NULL before calling the get_Fields() function, it's value is 0xcccccccc.
As far as I can tell, we close the recordset when we're done with it. Otherwise, we'd get an error message from Oracle saying we have too many open cursors.
Has anyone got any idea why this might be happening?
|
|
|
|
|
Hmmm, just a shot in the wild......
I had similar strange problems with Win2k, when I used the connection from a service app.
I removed the m_piRecordSet.Release(); because the = operator actually calls m_piRecordSet.Release(); .
It worked for me
A bit strange though...
- Anders
|
|
|
|
|
Hi,
One of my programs uses keyboard hook and shell hook. However, under win9x/ME it does not work as expected.
What's the point:
When Winscheduler is active and it is minimised on try bar...
If you minimize another program (e.g. Word, Acad 14, Excel ...), the icon of minimised program disappear from task bar. If you use ALT+TAB you can steel switch between programs.
Moreover, when you open a new window, it is not seen on the taskbar.
Here is the source code for the dll file:
<br />
<br />
#include "stdafx.h"<br />
#include "SystemHook.h"<br />
#include <stdlib.h><br />
<br />
#define ID_CMD_KEYPRESSED WM_USER+200<br />
#define ID_CMD_WNDCREATED WM_USER+201<br />
<br />
#pragma data_seg("SHARDATA")<br />
static HWND hwndMain = NULL;
#pragma data_seg()<br />
<br />
HWND ghWndMain;
HHOOK hHookKey;
HHOOK hHookShell;
<br />
static BOOL bHookInstalled;
<br />
HINSTANCE ghDLLInst;
<br />
<br />
BOOL APIENTRY DllMain( HANDLE hModule, <br />
DWORD ul_reason_for_call, <br />
LPVOID lpReserved)<br />
{<br />
switch (ul_reason_for_call)<br />
{<br />
case DLL_PROCESS_ATTACH:<br />
case DLL_THREAD_ATTACH:<br />
case DLL_THREAD_DETACH:<br />
case DLL_PROCESS_DETACH:<br />
break;<br />
}<br />
ghDLLInst=(HINSTANCE)hModule;<br />
return TRUE;<br />
}<br />
<br />
CSystemHook::CSystemHook()<br />
{ <br />
return; <br />
}<br />
<br />
SYSTEMHOOK_API LRESULT CALLBACK KeyboardProc(int nCode,WPARAM wParam,LPARAM lParam)<br />
{<br />
if (nCode >= 0) <br />
{<br />
if(nCode == HC_NOREMOVE)<br />
return CallNextHookEx(hHookKey, nCode, wParam, lParam);<br />
<br />
if (!(lParam & 0x80000000 || lParam & 0x40000000))<br />
{<br />
{<br />
static HWND h=::FindWindow(NULL,"WinScheduler");<br />
PostMessage(h , ID_CMD_KEYPRESSED , wParam, lParam);<br />
}<br />
}<br />
}<br />
return CallNextHookEx(hHookKey, nCode, wParam, lParam); <br />
}<br />
<br />
SYSTEMHOOK_API LRESULT CALLBACK ShellProc(int nCode,WPARAM wParam,LPARAM lParam)<br />
{<br />
return CallNextHookEx(hHookShell, nCode, wParam, lParam); <br />
}<br />
<br />
SYSTEMHOOK_API int WINAPI InstallHook (HWND hWnd, BOOL bCode )<br />
{<br />
int nReturn = 1;<br />
ghWndMain = hWnd;
<br />
if (bCode == bHookInstalled) <br />
return 0; <br />
<br />
if (bCode)<br />
{<br />
hHookKey=(HHOOK)SetWindowsHookEx(WH_KEYBOARD,(HOOKPROC)KeyboardProc,ghDLLInst,0);<br />
hHookShell=(HHOOK)SetWindowsHookEx(WH_SHELL,(HOOKPROC)ShellProc,ghDLLInst,0);<br />
if (!hHookKey)<br />
return 0; <br />
if (!hHookShell)<br />
return 0;<br />
bHookInstalled = TRUE; <br />
}<br />
else <br />
{ <br />
nReturn = UnhookWindowsHookEx(hHookKey);<br />
nReturn &= UnhookWindowsHookEx(hHookShell);<br />
bHookInstalled = FALSE; <br />
}<br />
return nReturn; <br />
}<br />
As it is seen, even if I am not doing anything in the ShellProc, the program does not work correctly. If i do not install the WH_SHELL hook, everything works fine.
Please help me. What may be the reason for this stupid behavior?
Best regards
Mustafa Demirhan
|
|
|
|
|
I'm not sure I understand what your code is supposed to do but I can spot something wrong :
hHookKey, hHookShell, bHookInstalled should be inside your SHARDATA section. They should be shared between processes.
I think ghWndMain should be inside as well. (hwndMain doesn't seem to be used ?)
#pragma data_seg("SHARDATA")
HHOOK hHookKey = NULL;
HHOOK hHookShell = NULL;
BOOL bHookInstalled = FALSE;
HWND ghWndMain = NULL;
#pragma data_seg()
-------------------------
Benoit Devigne
http://www.bdevigne.com
contact@bdevigne.com
|
|
|
|
|
I'm using MFC programming to implement a software. Of course there are "View, Doc, mainframe...etc" file.....
I've added a dialog box with a textbox for me to input some values. And I have separate file called ABC.cpp to do other things. In the ABC.cpp, I would like to pop up that dialog box to let user to input the value and then use that value in ABC.cpp. However, i got the following error message:
C:\XYZ\InputNum.h(21) : error C2065: 'IDD_INPUTNUM' : undeclared identifier
C:\XYZ\InputNum.h(21) : error C2057: expected constant expression
I did everything already:
CInputNum InputNum;
InputNum.DoModal();
num = InputNum.m_inputnumber;
Do you know why? and how to fix it? I don't want to make a global variable......
|
|
|
|
|
Looks like you are including inputnum.h without including resource.h for that translation unit. Its nicer if you can keep #includes out of header files, but including resource.h inside inputnum.h would probably solve the problem.
|
|
|
|
|
Wow........you are superb!!!
Thanks....
It works!!!!
|
|
|
|
|
Hi everybody,
I am developping a program named WinScheduler. I am using Win2000 and the program runs well under Win2000. However, there are some problems in Win9x. The program normally uses WH_KEYBOARD and WH_SHELL hooks. WH_SHELL is used to catch the newly opened top level windows.
However, under win9x it does not work as expected.
What's the point:
When Winscheduler is active and it is minimised on try bar...
If you minimize another program (e.g. Word, Acad 14, Excel ...), the icon of minimised program disappear from task bar. If you use ALT+TAB you can steel switch between programs.
Moreover, when you open a new window, it is not seen on the taskbar.
Please help me. What may be the reason for this stupid behavior? Everything works fine on Win2000 but nothing works on Win9x.
Best regards
Mustafa Demirhan
|
|
|
|
|
Hello, the codegurus around the world.
Life seems not to be easy among Windows OS.
At our company, we have had the problems among Windows OS, especially Windows Me and NT 4.0.
In that case, we had written the different code for each Windows OS.
So, before we write the code, we always check that this API supports by all or not.
In fact, I can't give you the answer, but Window 2000 gives us the useful API function.
But, it may not work for Windows 9x.....
Have a nice day!
-Masaaki Onishi-
|
|
|
|
|
This may be old news to everyone else, but I can't seem to compile anything with an STL header such as <vector> included without warnings. I've been asked to develop a project to compile with warnings set at level 4, but even a bare source file with a single line...
#include <vector>
...gives rise to 6 warnings.
Is there some way around this? Can I get better source code for the STL under Visual C++?
|
|
|
|
|
one line will fix it. put it before your STL includes.
#pragma warning(disable:4786)
-c
------------------------------
Smaller Animals Software, Inc.
http://www.smalleranimals.com
|
|
|
|
|
or....
#pragma warning(push, 3)
include all your STL headers here...
#pragma warning(push, 4)
- Anders
|
|
|
|
|
bonjour!
i've got a little worker thread in my CDocument derived class. i've also defined a message and a message handler in my CDocument. i tried to post my message with PostMessage(NULL,MYMESSAGE,...) but it didn't work. i think the decleration of MYMESSAGE is ok (#define UWM_MYMESSAGE (WM_APP + 7)
what's the right way to post messages to a cdocument?
thx benedikt
|
|
|
|
|
PostMessage sends the message to a window, and a worker thread doesn't have a window associated with it. Get a handle to your application's main window and use it, e.g.
HWND hMain = AfxGetMainWnd()->m_hWnd;
::PostMessage(hMain, MYMESSAGE, 0, 0);
|
|
|
|
|
thx for your reply. i tried it with the following statement but it does not work.
CWnd* m_pWnd = (CWnd*)AfxGetMainWnd();
CString* s = new CString(cstrName);
PostMessage((HWND)m_pWnd,UWM_PROGRESSDELETE,0,(LPARAM)s);
the afx_msg function is never called.
any ideas?
|
|
|
|
|
The AfxGetMainWnd() will return the main window of the thread that made the call and it's not likely to be to one you want it receive the message.
Furthermore, you should avoid using MFC objects in your thread if they have been created in another thread. MFC doesn't handle that very well...
My prefered solution is to pass the HWND you need to your thread as a parameter :
CWinThread* pThread = AfxBeginThread(MyThread, (HWND)m_hWnd); // or any HWND you want
UINT MyThread(LPVOID pParam)
{
HWND hWnd = (HWND)pParam;
::PostMessage(hWnd, ...
}
You can pass a CWnd* as well but remember you want be able to access all its methods. In your case, if you only want to do a pWnd->PostMessage(...), it will work.
-------------------------
Benoit Devigne
http://www.bdevigne.com
contact@bdevigne.com
|
|
|
|
|
Hi all:
Let two things sink in. (It took time for me to, anyways!)
(i) He just wants to access just the CDocument-derived object--not a window. CDocument is not derived from CWinThread. There can be command rounting via MFC, but NO message pump.
(ii) This is not a GUI thread, but a worker thread.
So, why bother with window handles and PostMessage API at all?
The solution is as simple as just passing the CMyDocument object as is!
CWinThread* pThread = ::AfxBeginThread( MyWorkerThreadProc, this );
In the worker thread proc
UINT MyWorkerThreadProc( void* pParam )
{
if( doc is no longer around )
{
return -1;
}
else
{
CMyDocument* pDoc = (CMyDocument*) pParam;
pDoc->CallAnyMemberFunction();
}
return 1;
}
Pl. correct me if I got something wrong. Thanks.
-- Ajit
Your project today is your great-grandchildrens' "ancestor clock."
|
|
|
|
|
thx for your answer. but it doesnt really work. CDocument don't have a HWND. here are all the relevant functions of my thread. maybe something other is wrong.
//the function which starts the thread
CUserManagerDoc::fnDeleteUser(CStringList &lstToDelete)
{
//is thread running?
if(bDeleteRunning)
{
MessageBox(NULL,"Es wird gerade gelöscht!","Achtung",MB_OK|MB_ICONEXCLAMATION);
return 1;
}
..... some code ....
bDeleteRunning = true;
pThread = AfxBeginThread(fnThreadDeleteUser,this);
return 1;
}
UINT CUserManagerDoc::fnThreadDeleteUser(LPVOID p)
{
//start the function
CUserManagerDoc* me = (CUserManagerDoc*)p;
me->fnThreadDeleteUser();
return 0;
}
//the thread function
void CUserManagerDoc::fnThreadDeleteUser()
{
..... some code ....
CString* s = new CString("Test");
CWnd* m_pWnd = (CWnd*)AfxGetMainWnd();
PostMessage((HWND)m_pWnd,UWM_PROGRESSDELETE,0,(LPARAM)s);
}
//message handler for the user defined message
LRESULT CUserManagerDoc::OnProgressDelete(WPARAM wParam, LPARAM lParam)
{
//get the text
CString *s = (CString *)lParam;
........ some code ......
return NULL;
}
|
|
|
|
|
OK. Got the picture almost fully.
Just one more part. Guess you have to look at how the message map entries for the UWM_PROGRESSDELETE look like in the project (not just in the Doc).
Since CDocument is not a CWnd (and also not a CWinThread), MFC will NOT find a way to directly route UWM_PROGRESSDELETE to CUserManagerDoc.
Therefore, you might have to add ON_THREAD_MESSAGE entries in CMyView or CMyFrameWnd where MFC will route these messages. Then, you could arrange for MFC to forward those to CDocument....
I would probably go for a more lengthy but a very straightforward and clean solution as following.
Derive a CMyWorkerThread from CWinThread class, and add ON_THREAD_MESSAGE entries for PROGRESSDELETE in CMyWorkerThread class, *not* in the CUserManagerDoc class.
Have a CMyWorkerThread* as m_pThread in Doc. Instantiate CMyWorkerThread on the heap in a doc function, and then call m_pThread->Create() to get the worker thread going. You can also cache the doc ptr as a member variable into the CMyWorkerThread class. If so, ensure you say
m_pThread->m_pCreatingDoc = this;
before calling m_pThread->Create().
To use: In CUserManagerDoc, call
m_pThread->PostThreadMessage( UWM_PROGRESSDELETE, 0, (LPARAM) pData );
To access Doc from CMyWorkerThread handler for ProgressDelete(), just use the cached ptr. (Some multi-threading synch object might be necessary to ensure m_pDoc in CMyWorkerThread is valid.)
This will always work. See if it is suitable for your needs.
-- Ajit
Your project today is your great-grandchildrens' "ancestor clock."
|
|
|
|
|
thanks for your detailed answer. i tried it with the first way you mentioned. I added the necessary message functions in my CMainFrame class. The message map handels the messages via ON_THREAD_MESSAGE(UWM_PROGRESSDELETE, OnProgressDelete) and ON_THREAD_MESSAGE(UWM_PROGRESSCREATE, OnProgressCreate). The CDocument function which stores the thread retrieves a window handle via m_pWnd = (HWND)AfxGetApp()->m_pMainWnd.
My thread function calls the function:
CString* s = new CString(cstrName);
PostMessage(m_pWnd,UWM_PROGRESSDELETE,0,(LPARAM)s);
but my message handlers are never called.
i think i don't really understand your second solution. creating the CMyWorkerThread is clear. caching the doc ptr too. but i'd like to send a message to something where i can savely make some changes on my user interface. i think you mentioned how to send messages into the running thread and not vice versa. or do i really understand nothing...
|
|
|
|
|