|
If you plan to distribute this, it would be against your EULA. You're not allowed to modify system DLL's.
Further, I can't help but think there has to be a different solution to the problem.
|
|
|
|
|
Is this simplified picture of message pumping correct?
1. The user clicks a mouse button.
2. The mouse driver puts an item into the system input queue.
3. A system thread, which handles user input, retrieves this item and, using
coordinates recorded by the driver, determines to which window this message
should be posted. Mouse messages are always sent to the window under the
cursor (unless another window has captured mouse input).
Given the window handle the system detemines the thread to which this window
belongs and posts WM_LBUTTONDOWN and WM_LBUTTONUP messages to the
message queue of this thread. Note, the message is posted to only one message
queue since the system knowns to which thread the window belongs.
4. The application object, derived from CWinApp, will pickup the message from its thread message queue. Then route this message to the appropriate controls/windows.
5. Button window procedure receives WM_LBUTTONUP message and do the following:
(i) update the display of the button (depressed state and then the release state.)
//QUESTION: SendMessage( ) OR PostMessage( )??
(ii) sends WM_COMMAND/BN_CLICKED notification to "the parent window" or a "particular" control.
(iii) posts WM_COMMAND/BN_CLICKED notification to the application/thread message queue.
5. Message map can be "expanded" to a subroutine that searches the message map upon reciept of a message/notification, then route the message to "appropriate" message handler in response a mapped message.
(This brings up the issue of message routing. ie. Things like searching the view class maps, then the document class, then the frame windows, then the app...)
//Example of a handler:
void CMyDlg::OnButton1()
{
// TODO: Add your control notification handler code here
}
Thanks
|
|
|
|
|
Can anyone explain why this template does not work with signed types?
template<class t=""> T IsolateBits(T x, int bit1, int bit2)
{
T v=0;
for(int b=0; b < bit2-bit1; b++)
{
v = (v << 1) | 0x01;
}
for(int b2=0; b2 < bit1; b2++)
{
v = (v << 1);
}
return (x & v);
}
Basically, the template is supposed to change all bits out of range bit1-bit2 to 0's...and it works perfectly unless the class inputed is signed. Any suggestions on how to fix this?
--Jesse
|
|
|
|
|
Your code won't work as a C function either.....I believe the high bit in signed integers is "latched" and will be rotated into the next bit position following a rotation.
|
|
|
|
|
How is this done? Do you have a link to an example?
|
|
|
|
|
i assume you mean 'how do i put a combo box on a toolbar' and that is easy ... just make it a rebar (CReBarCtrl) and plonk it on one of the bands ... s'easy really ... app wizard can generate it for you and all you have to do is edit the dialog template to add the combo box
"every year we invent better idiot proof systems and every year they invent better idiots"
|
|
|
|
|
Actually, I wanted to put it onto a CToolBar. I finally found an example in the MSDN samples. Subclassed CToolBar and added a CComboBox to it. Created a new toolbar resource with just one button, and then when creating the CToolBar I replaced that button with the combo box.
|
|
|
|
|
I have derived a new static control where one can the font of the text contained in the static control. However if the font size is set very big then half the text is obscured. Is there a way I can find out the new dimensions of the text and as such enlarge the static control dynamically.
|
|
|
|
|
use GetTextMetrics() and adjust the size of your static control using MoveWindow()
"every year we invent better idiot proof systems and every year they invent better idiots"
|
|
|
|
|
Does anybody know how to implement a ruler control such as found when one is editing or creating a dialog in MSDEV, or know of a sample application with source code.
|
|
|
|
|
i would create a toolbar and plonk a static control on it that you resize as the toolbar resizes ... in the static you can set the mapping mode to whatever you want and draw the markings for the measurements
could be other ways but hey...
"every year we invent better idiot proof systems and every year they invent better idiots"
|
|
|
|
|
static control on it that you resize as the toolbar resizes
And any help you can offer on the toolbar resizes? Post your code lines here please.
|
|
|
|
|
hmmmm
check out CDialogBar ... it becomes part of the main window and doesnt float around which may be better for a ruler ... plonk the static control in and catch size change messages in the frame window and change the static control size from there
it might fit ur needs more
"every year we invent better idiot proof systems and every year they invent better idiots"
|
|
|
|
|
check out CDialogBar ... it becomes part of the main window and doesnt float around
Are you sure the dialog bars don't float around, or even dock around?
PS. Learn a little more before you post answers, pleeease.
|
|
|
|
|
Wordpad!
Wordpad offers just such a ruler, and it's source comes with VC++.
|
|
|
|
|
|
The MSDN tells me that the thread process for CreateThread must be a function of the following form: DWORD WINAPI ThreadProc( LPVOID lpParameter ).
When I implement this as a simple global procedure I have no problems but if I make the function a member of a class (SerialComms for example) C++ refuses to accept it as a parameter and complains about an illegal cast. Nothing I have tried could coax it into recasting to an acceptable value. The pointer it wants is,
DWORD (WINAPI *ThreadFunction )(void *)
but when I point to a member function it actually sees,
DWORD (WINAPI SerialComms::*ThreadFunction )(void *)
As far as I am concerned these are identical except for the namespace. The linkage is identical also so C++ should only warn me and not kill the compile. I have solved this problem as follows:
union
{
DWORD (WINAPI SerialComms::*x )(void *);
DWORD (WINAPI *y )(void *);
} z;
// Get the read thread procedure address. This is a weird "cast" method.
z.x = ThreadFunction;
m_readThread = CreateThread( NULL, 0, z.y, 0, 0, &m_threadId );
It works but I am not real happy with a "smartass" solution like this.
Question? How can I recast a member function so I don't have to trick C++ into a funny union "cast"? (For C++ purists, my apologies. I'm an old, unreformed assembler and C hacker!)
|
|
|
|
|
Generally, you would declare a member threadproc as static . This placates the C interface, which has no knowledge of member fns. It sort of promotes the fn from out of the classes vtable space into the global arena.
The only sticky point you'll have is that now that the fn is static it can't access the non-static members of the class (static fns have no this pointer). To get around this (no pun) limitation, pass the this pointer as the lpParameter.
later... Actually, your fix is kind of neat - - does it get around the member access problem?
|
|
|
|
|
Thanks for your thoughts Tim. The problem with static member functions is that you have the same function for each instance. This means that there can only be a single thread running for all of my read processes. This is not suitable for my application. I need a unique thread function in each class instance for a number of reasons.
Now comes the interesting part. My little "cast" definitely works for compiling a member function to be the thread procedure. However, class members are ONLY visible if a pointer to the class is passed as the thread parameter. For example (called from my object initialisation routine),
m_thread = CreateThread( NULL, 0, z.y, this, 0, &m_threadId );
NOTE that I do not use the lpParameter at all, I just pass it. I acces members without a pointer i.e. m_count not ((int *)lpParameter)->m_count. If lpParameter is set to null, the function is still started by the CreateThread but "this" is seen as NULL and the member functions are not visible. I read the doco to mean that the lpParameter is passed for my use but it seems that Windows is using it to overwrite "this" somehow. Go figure....
|
|
|
|
|
I think I know why this behaviour can occur:
When calling a instance method, std. C++ uses one "hidden" param "this". Since you have done your nice union and CreateThread is calling "straight" into your instance method using expecting __stdcall and your C++ method is expecting "this-call" unless other specified.
It it is so:
Why does you get this ptr. since as far as I know, "this-call" is expecting "this" in the EXC register, otherwise __stdcall and "this-call" passes params, and cleaning up, in the same manner.
/mario
|
|
|
|
|
You are 100% correct. I have traced this through and I now understand what is happening. THIS METHOD IS EVIL. DO NOT USE! It works by accident. My "smartass" technique is just that - smartass.
When a method with a single parameter like my thread function is called in C++, the parameter is pushed onto the stack and then the address of the instance object is pushed. This is the hidden "this" parameter. My member thread function understands these two stack entries as "this" and lpParameter.
The CreateThread only pushes ONE parameter when it calls the thread function. This is meant to be lpParameter but my function mistakes it to be "this". The second stack entry is rubbish but my function takes it to be lpParameter. So if I call CreateThread from a member function and pass "this" as the lpParameter it all seems to work as long as I don't try to use lpParameter. But in fact my stack is already corrupt. Because the thread has its own stack and when it returns this is destroyed, I don't actually blow anything up. But would you bungee jump 300 metres on a 10 kilo fishing line? Back to the drawing board.
|
|
|
|
|
Well, looks like you beat me to it! Funny - I could have sworn I was replying to your previous message, but your posting seemed to intervene and mess up the ... er ... thread...
Anyway, I do recommend beginthreadex if you are using anything in the standard library. And consider using static?
|
|
|
|
|
Sorry for jumping in on top of you. No excuses!
|
|
|
|
|
_beginthreadex is recommended, check the article in MSDN.
|
|
|
|
|
Well, actually you only have one function anyway - its the instance data that is duplicated. So, if one class spins many threads, you need locks on the data. If several instances spin one thread each (sort of begs the question) you're still time slicing the same code. Static local vars would be a problem.
But to the interesting stuff - here's some code I've been playing with.
I first tried to reproduce your code using CreateThread - but since I am using some std stuff here, _beginthread turned out to be a good deal safer, as it links with a 'thread safe' version of the runtime.
The code below should compile for both Borland CB4 and VC6. The only syntactical change I had to make was in the assignment to z.x. Borland complained that ThreadProc alone was ambiguous.
The call to _beginthread shows the same behavior for the this pointer - if NULL, an access violation occurs at runtime. If this , members are accessed transparently.
Don't know if this is a serindipitous side effect, as Mario suggests, or something we can rely on, but certainly is interesting.
Note that there are no locks here, and the calls to cout can get a bit mixed (moreso in debug).
#include <windows.h>
#include <process.h>
#include <iostream>
using namespace std;
class Fred {
private:
int m_nThreadCount;
union {
void (__cdecl Fred::*x )(void *);
void (__cdecl *y )(void *);
} z;
public:
void __cdecl ThreadProc(void*);
void StartThread();
Fred():m_nThreadCount(0){};
};
void Fred::ThreadProc(void* lpParam) {
++m_nThreadCount;
cout << "Hey its me Fred!" << " Count is " << m_nThreadCount << endl;
}
void Fred::StartThread() {
z.x = &Fred::ThreadProc;
_beginthread(z.y, 0, this);
cout << "Thread started..." << endl << flush;
}
int main(int argc, char* argv[])
{
cout << "Thread test!" << endl;
Fred fred;
fred.StartThread();
int x;
cin >> x;
return 0;
}
I guess the next step is to look at some registers and see whats going on. BTW you might want to use _beginthreadex . I wanted to keep things simple.
Lastly, it seems to me that if the union trick works, there must be a way to cast the pointer passed to _beginthread . Hmmm...
this certainly makes for an interesting thread though...
|
|
|
|