|
I'd be doing a better one if I could see more of your answers.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Hi,
I have created a ATL toolbar using CreateWindow() API and attached ToolButtons using
AddButtons() API.
Now I want to add tooltips to these buttons.
How to add tooltips to the ATL toolbar.
|
|
|
|
|
Windows 7, Visual Studio 2008, MFC, C++
Intellisense says the arguments for this method are:
Send( const void *lpBuf, int nBufLen, int Flasg = 0 )
An MSDN web page has example code that looks like this:
Send((LPCTSTR)m_sendBuffer + m_nBytesSent,
m_nBytesBufferSize - m_nBytesSent);
Either way, I cannot get the right combination. I have:
SYSTEMTIME m_current_time;
GetSystemTime( &m_current_time );
int t1 = sizeof( m_current_time );
int chars_sent = m_C_Server_Send_Time_Socket->Send( (LPCTSTR) m_current_time, t1, 0 );
Where m_C_Server_Send_Time_Socket is the object created from CAsyncSocket to do all the transactions once the connection has been established.
How should the arguments to Send() be written?
Thanks for your time
modified 18-Sep-12 22:50pm.
|
|
|
|
|
bkelly13 wrote: How should the arguments to Send() be written? As described in the documentation[^] is usually the right way. In your case why would you cast to LPCTSTR when it specifically states to cast to const void* ? So your code should look like:
int chars_sent = m_C_Server_Send_Time_Socket->Send((const void*)&m_current_time, t1, 0 );
Maybe a bit of a refresher about casts, pointers and the addressof operator would be useful.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
I am sure I tried that. I probably had a typo and did not recognize it.
Thank you for taking the time to reply.
Thanks for your time
|
|
|
|
|
Here is the thing: In C/C++ every pointer is automatically casted into (const void*) and every non-const pointer is automatically casted into (void*) . The msdn web page used cast just because of the pointer arithmetic involved, as you see they add an integer value to the start of the buffer: (LPCTSTR)m_sendBuffer + m_nBytesSent . They cast the buffer pointer into LPCTSTR because they want the addition to step the pointer with *byte* granularity. The problem with this is that LPCTSTR can translate not only to (const char*) but also into (const wchar_t*) (when the project character set is unicode, and note that wchar_t is a type whose size is 2 bytes!) so I guess MS guys made a mistake here and (LPCTSTR) is a bug (if the project character setting is set the unicode), they should have used (char*) or its equivalent in winodws: LPSTR or const char* or LPCSTR or something like that, something that is a *byte* pointer. Your problem is that you try to convert an instance of your struct into a pointer. You can not convert an instance into a pointer! You can converty only a pointer into a different type of pointer and in rare cases conversion might be needed between pointer and integral types.
SYSTEMTIME m_current_time;
GetSystemTime( &m_current_time );
int t1 = sizeof( m_current_time );
int chars_sent = m_C_Server_Send_Time_Socket->Send( (LPCTSTR) m_current_time, t1, 0 );
int chars_sent = m_C_Server_Send_Time_Socket->Send( (LPCTSTR) &m_current_time, t1, 0 );
int chars_sent = m_C_Server_Send_Time_Socket->Send( &m_current_time, t1, 0 );
Note that using (LPCTSTR) is a bug even on microsoft's side! You need to convert your struct pointer into a (char*) only if you want to step your pointer with byte precision!
SYSTEMTIME m_current_time;
SYSTEMTIME* p = &m_current_time + 1;
SYSTEMTIME* p = &(&m_current_time)[1];
char* p = (char*)&m_current_time + 1;
void* p = (char*)&m_current_time + 1;
const void* p = (char*)&m_current_time + 1;
Note that an addition or a substraction on a pointer always steps the pointer with the size of the type the pointer points to (like when you indexing into an array of the specified type). For this reason you can not step void pointers without casting them into something else - the size of void isn't defined.
|
|
|
|
|
But using LPCTSTR ensures that the pointer is incremented by the number of characters (whether Unicode or ASCII) not the number of bytes, so Microsoft are doing it right.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
If we speak of unicode and wchar_t then its not guaranteed that the data is transferred per character over the network, the variable name they use for incrmenting also reflects this: m_nBytesSent . They code heavily relies on the fact that LPCTSTR==LPCSTR in their case. Changing to unicode charset would introduce a hidden bug that compiles silently. If you decide to write code that has to compile with both ansi and widechar setting then using LPCTSTR is valid in many cases but this is an exception. I myself question the usefulness of supporting both ansi and widechar these days (so I don't anymore use defines like LPCTSTR and LPSTR) since its pain in the ass to write a program that compiles with both settings and today we can say that the majority of machines runs NT whose native is utf16. Its also a pain to search for bugs that arise only with one of the settings.
|
|
|
|
|
You are quite right, I failed to read that in enough detail; my apologies. I should know better than to challenge your knowledge.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Your comment is quite okay, this is a place for technical debates. I'm open to challenges anyway.
|
|
|
|
|
I searched for their code and I guess I found the codepiece OP is talking about: http://msdn.microsoft.com/en-us/library/aa268613%28v=vs.60%29.aspx[^]
They are using ansi string literals (without TEXT macro) so their code wouldn't compile with uncode charset, for this reason I guess they haven't tried this code with unicode setting so the bug could easily hide there.
|
|
|
|
|
Yes, it is rather a poor example.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
This is pretty cool. You guys can disagree about something, go to the facts, then come to an agreement on those facts. All without getting riled up in the slightest. Thanks for thinking and discussing this and thanks for setting a good example.
Thanks for your time
|
|
|
|
|
That's probably because we are just the same as you. Part of the reason for visiting this site is to learn new things from reading answers, getting links to new information, and discussing issues with others. And even after 40+ years working with computers, I still consider myself a novice.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
Becoming an "expert" even in an a very specialized area (small part of the whole computer science miracle) always involved finding out how stupid I am. Computer science covers too many areas for someone to learn even within his full lifespan, not to mention its rapid change over time...
|
|
|
|
|
Hello pasztorpisti,
After reading your first post a few times I think I have figured out your message.
In the first code block you are describing my error in the OP and providing the Whys of the situation.
In the second code block you are describing the techniques used to access the various components of the object. I did not ask that, but you provided it as a necessary bonus.
Please comment and confirm/deny my interpertation.
Edit: I addressed this to a) recognize him specifically, b) identify the post. However, every reader is invited to respond.
Thanks for your time
modified 30-Sep-12 12:36pm.
|
|
|
|
|
You are welcome! However the cast to (char*) is barely an access of subcomponents, its rather accessing the contents of the object as binary byte array that should be considered as a primitive form of serialization. It might not work if you share the binary data for example between two machines that are different in endianness or if the class/struct member alignment used by the compiler of those systems is different and you don't set alignment explicitly (that isn't always possible)...
Note: In a simple program that isn't crossplatform its okay to serialize data this way. Lets say you write an exe that communicates over sockets with other machines - if all the machines run windows and you copy the same executable to all machines then everything will be fine, it would be a mistake to overcomplicate your serialization in this case. However the problem I wrote about (endianness, alignment) arises much often on linux platform where the underlying machine architectures can differ significantly and the same program has to be recompiled.
modified 30-Sep-12 14:42pm.
|
|
|
|
|
Hello,
I have an application exe and COM dll.
- In Exe I have like this :
class CMyExeApp : public CWinApp
{
...
public:
CMyObject * m_pMyObject;
public:
virtual BOOL InitInstance();
....
}
extern CMyExeApp theApp;
All works fine between the Exe and the COM dll.
What I need is to get the instance of Class CMyExeApp (theApp) to get the reference to m_pMyObject IN THE DLL
I tried this in Dll :
HMODULE hModule = GetModuleHandle(CURRENT_EXE_NAME);
but i didn't know what i do after
any help please
|
|
|
|
|
Put an exported DLL function to your DLL that you call from your exe. You could pass the CMyObject pointer to your DLL as a parameter.
|
|
|
|
|
first thanks for reply
But I dont like modifing any thing in code (i should add a new interface for that)
SO i need just to get a pointer to this object.
can I get it by adress or something else?
|
|
|
|
|
If you don't like modifying the code then just leave it as it is.
|
|
|
|
|
Accessing a class residing in another module has many implications. Finding out if your modifications are valid or not can be decided just by looking at the code.
|
|
|
|
|
khaliloenit wrote: but i didn't know what i do after
There is nothing you can do since there is no direct back link from the Windows handle to the class object. You will have to modify both your exe and your DLL to pass the pointer across from one to the other.
One of these days I'm going to think of a really clever signature.
|
|
|
|
|
If it's a COM dll then passing a C++ object to it is almost certainly a bad idea; COM is meant to be language neutral. Provide a COM compliant interface to the C++ object and pass that to it.
Steve
|
|
|
|
|
Environment Windows 7, Visual Studio 2008, MFC, C++
Goal: create an asynchronous server and client class to demonstrate a simple server client operation. Base class for Server and Client is CAsyncSocket. IP address 127.0.0.1, port 49000
Status: The dialog has buttons for the server to Initialize, Listen, and Accept, so far. It also has buttons for the client to Initialize and Connect. Both have Close buttons. One dialog but two separate classes. Umm, make that three counting the CAsyncSocket class used by the server to communicate after the two have connected.
In the server group buttons Initialize and Accept appear to work correctly, in that order of course. The returned status is TRUE and wsa error code is zero. The Listen button creates a new object to handle the transactions and gets WSA code 10035 WSAEWOULDBLOKC, would block, treated as an expected result. Good so far. Now, hopefully, the server object is waiting for the client.
Then the buttons for the client are selected to Initialize, wsa error = 0, then Connect to the same IP address and port. It gets wsa error code 10048, WSAEADDRINUSE, address already in use. Hmmm. Yeah, it is in use, but if it is not in use by a server then the client cannot connect.
I believe I have the code working as I expect, but there is a fundamental error in my logic. Is this sufficient info for someone to tell me what I have done wrong or omitted? What might that error be?
Thanks for your time
|
|
|
|