b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

win7放大镜还原_win7 magnify_registerwindowmessage

电脑杂谈  发布时间:2017-02-01 19:27:30  来源:网络整理
registerwindowmessageregisterwindowmessage

Messages in the WM_USER + x range are neither obsolete now, nor were they obsolete at the time of writing. They have never changed their semantics or become less appropriate. They have always had and have to this day a succinct meaning: It is the range of messages for private use by a window class.

If you are the owner of a window class, you are free to use each and every message in this range. There are no collisions with other window classes using the same numeric values for their private messages either. Or have you had issues with TTM_ACTIVATE messages being mistaken for TB_ENABLEBUTTON messages lately (both are WM_USER + 1)?

You should consider updating the article with facts, instead of babbling about WM_APP being the new WM_USER. Those constants define the start of different ranges of messages, with different applicability. Both ranges are valid, and neither has inherent problems. For reference see [].

Hi all,

For registered messages in a WTL app, is there a special macro to use in my WTL message map other than MESSAGE_HANDLER(ID, func)? I've registered the message in both processes, but I never see the message.

I don't seem to be getting any registered message. I put this in my message map:

MESSAGE_RANGE_HANDLER(0xC000, 0xffff, OnAnyRegisteredMessage)

And then added this handler:

LRESULT OnAnyRegisteredMessage(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled)
{
   TRACE(_T("msg = %d, wParam = %d, lParam = %d\n"), uMsg, wParam, lParam);
   bHandled = ~bHandled; // Do this so the message is still handled
   return 0;
}

I'm sure that the messages are being sent to the app, but this code never gets hit.

Thanks,

Aaron

I've never used WTL, and never worried about it. You'd have to check the WTL documentation.

Lumping all the messages together would be a really poor approach, it would be unfortunate if WTL was so defective that you were forced to use such a solution. I would find it hard to believe that something this essential was missing, so there must be a macro somewhere. Why not just browse the WTL header files?

I was simply checking for all registered messages to see if my window was receiving them. The messages were going to the frame and were not being passed along to the view.

But that also didn't tell me how to code the message map for registered messages. There is no macro for registered messages in WTL. I created one and added it to my #define's:

#define REGISTERED_MESSAGE_HANDLER(msg, func) \
	if(uMsg == *((UINT*)(&msg))) \
	{ \
		bHandled = TRUE; \
		lResult = func(uMsg, wParam, lParam, bHandled); \
		if(bHandled) \
			return TRUE; \
	}

Then you'd simply add it to your message map:

REGISTERED_MESSAGE_HANDLER(s_iRegMsgID, OnBlah)

In MFC, only WM_COMMAND and WM_NOTIFY messages are routed; no other messages are routed to the view, because that is the specification. I would suspect that WTL implements a similar pattern. Messages other than WM_COMMAND and WM_NOTIFY would not be routed. Why would you expect them to be? Message routing is used only for menu/toolbar items.

If you want any other message sent to your view, it is your responsibility to send it to the active view from the main frame.

Could you please let me know how does the below code of macro work

#define REGISTERED_MESSAGE_HANDLER(msg, func) \
	if(uMsg == *((UINT*)(&msg))) \
	{ \
		bHandled = TRUE; \
		lResult = func(uMsg, wParam, lParam, bHandled); \
		if(bHandled) \
			return TRUE; \
	}

What does specifically if(uMsg == *((UINT*)(&msg))) line mean?

Tom

uMsg == *((UINT*)(&msg)) casts the address of msg (which is a macro param) to a (UINT *), and then reads the value in that spot. It's the long way around for reading the value, but I had to do that so it would compile. (It may work without all the casting, but I haven't tried it in a while.)

So here's how it gets used. First, you have to declare the var that holds the registered window message.

// ID: MyMsg
// WParam: Not Used
// LParam: Not used
static unsigned int s_iMyMsg = ::RegisterWindowMessage(_T("MyMsg"));

Then, to handle this message, you put this into your message map:

REGISTERED_MESSAGE_HANDLER(s_iMyMsg, OnMyMsg)

A registered message handler has the same arg list as a regular message handler:

// LRESULT OnMyMsg(UINT /*uMsg*/, WPARAM wParam, LPARAM lParam, BOOL& bHandled)

HTH.

Hi,

many thanks for this wonderful article, it helped me a lot and permitted to avoid many problems.

I implemented a new way of generating truly unique message ids: I use a class which generates a UUID and concatenates it to the message name passed to RegisterWindowMessage.

I think it's an affordable solution, as the uuid is normally generated once for program run if you use global variables, or static member variables.

To use it just do this:

GENERATE_MESSAGE_ID(MSG_NAME)

and as usually put

ON_REGISTERED_FUNCTION(MSG_NAME,...)

into your message map

You must also link your program to the Rpcrt4.lib library.

Jan Chorowski

The class definition follows:

#include <string>

#define GENERATE_MESSAGE_ID(name) const static CMessageId name(#name);

class CMessageId

{

private:

UINT messageId;

public:

CMessageId(const char* messageName="")

{

UUID uuid;

std::string str(messageName);

unsigned char *ustr;

UuidCreate(&uuid);

UuidToString(&uuid,&ustr);

str+='_';

str+=(char*)ustr;

RpcStringFree(&ustr);

messageId=RegisterWindowMessage(str.c_str());

}

UINT getId() const {return messageId;}

operator UINT() const {return messageId;}

~CMessageId(void)

{}

};

Hi,

Your work is helpfull. However, while creatting a custom control, I perefer to create a blackbox.

Whenever I use the control, everythig must be standart. even if I would use global or static variable, in every declarations in your approach, program will create a unique message. if I would not use global or static variable, in every call of GENERATE_MESSAGE_ID creates unique message ID. For example, if you use 6 custom controls, program creates, at least, 6 diffirent unique messages. If I put them into an other custom control. The parrent custom control for the same massage, uses different message ids. That could create confutions in many situatons.

Hence, I recomend, it is better way to use what essay says.

Very interesting article and very helpful. I tried this and it *seems* to work fine. Only problem I have is a deadlock.

I rewrote it a little to a single-threaded solution (well not all, but the GUI part anyway), and I still get a deadlock!

Do you think you can help with this little snippet of code?

template<typename T>
    void AddFilesThread(T* pFilesArg)
 {
     pp<UINT> pProgress = new UINT[si.dwNumberOfProcessors];
     vector<CString>* pFiles = (vector<CString>*)pFilesArg;
        EnumValuesArray* pFilesReg = (EnumValuesArray*)pFilesArg;
     DWORD dwSize;
     //pp<bool> pCancel = new bool;
      //*pCancel = false;
       
      // Beware that size() returns the element count; NOT the highest index (which is count - 1)!
      if ( typeid(pFilesArg) == typeid(vector<CString>*) ) dwSize = (DWORD)pFiles->size() - 1;
     else if ( typeid(pFilesArg) == typeid(EnumValuesArray*) ) dwSize = (DWORD)pFilesReg->size() - 1;

     //ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::LOCK_TREE) ) );
        m_Tree.LockUpdate();
      //ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::CALL_SHOWWINDOW, &ProgressDlg, SW_SHOW) ) );
       ProgressDlg.ShowWindow(SW_SHOW);
      DoTasks(true);
        ZeroMemory(pProgress.GetPointer(), sizeof(*pProgress) * si.dwNumberOfProcessors);
     //NewThread(&CKantanAnimeDlg::UpdateGUIThread, this, pProgress, dwSize, pCancel)->m_bAutoDelete = true;

      CThread* pThread = NewThread(&CKantanAnimeDlg::AddFilesThread2<T>, this, pFilesArg, /*pCancel, */pProgress, dwSize); // Do some processing

        UINT nTotalProgress;
      UINT nLength = si.dwNumberOfProcessors;
       int nCount = 1;

     while(pThread->Running())
      {
         nTotalProgress = 0;
           for (UINT i = 0; i < nLength; i++) nTotalProgress += pProgress[i];
         ProgressDlg.m_ProgressText->Format("Loading encoding list. Please wait...\nAdding file %u of %u...", nTotalProgress, dwSize);
          ProgressDlg.m_Progress.SetPos( (int)( (float)nTotalProgress / dwSize * 100 ) );
           //ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::CALL_SETPOS, &ProgressDlg.m_Progress, (int)( (float)nTotalProgress / dwSize * 100 )) ) );
          if (nCount++ == 20) // Update every 200 ms
            {
             //ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::CALL_UPDATEDATA, &ProgressDlg, FALSE) ) );
             ProgressDlg.UpdateData(FALSE);
                nCount = 1;
           }
         //DoTasks(false);
         DoMessageLoop();
          //if (*pCancel) break;
            Sleep(10);
        }

       //ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::UNLOCK_TREE) ) );
      //ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::CALL_SHOWWINDOW, &ProgressDlg, SW_HIDE) ) );
       m_Tree.UnlockUpdate();
        ProgressDlg.ShowWindow(SW_HIDE); // DEADLOCK!!!!
      DoMessageLoop();
      //DoTasks(false);
     //*pCancel = true;
        ProgressDlg.bCancel = true;
   }

The deadlock appears when trying to hide the Progress Dialog (see above). I don't know WHY it does that. Is it waiting for an answer from the dialog's message loop? It could be if the message was POSTED to the message queue, since no message processing would be done. This deadlock also occurred in the multi-threaded solution, when the hide window code was executed in the main window's windowproc.

CKantanAnimeDlg dlg;
	m_pMainWnd = &dlg;
	dlg.Create(IDD_KANTANANIME_DIALOG);
	dlg.ShowWindow(SW_SHOW);

	pp<EnumValuesArray> pArray = dlg.pRegForPlaylist->EnumValues("");
	if (pArray)
	{
		//pp<EnumSubKeysArray> pMMArray = pArray;
		//size_t nCount = 0;
		//NewThread(&CKantanAnimeDlg::AddFilesThread<EnumValuesArray>, &dlg, pArray)->m_bAutoDelete = true;
		dlg.AddFilesThread(pArray.GetPointer());
	}

That's how the function is called. Any suggestions? This deadlock madness is driving me *crazy*.

-- modified at 17:50 Tuesday 29th August, 2006

I'm guessing here that AddFilesThread creates threads to add files to a list. There are many, many things wrong with this code.

First, it sits and polls pThread->Running(). This is already a serious design error. Having started the threads, the code should IMMEDIATELY return and not sit polling anything. So get rid of that entirely.

The update of progress bars and text must be done by having the thread PostMessage to the window that will handle these updates. That whole update loop is completely wrong. The DoMessageLoop is an indication that the code is irremediably flawed.

When the thread completes, it can PostMessage a notification that it has finished and that's where you unlock the update and clean up. The whole approach here is a misguided attempt to makes threaded code work like non-threaded code, and this is always a mistake. Learn to think asynchronously.

I wouldn't even consider looking for deadlock issues until the code is rewritten to be sane. This code is just out-and-out wrong. There should be no update loop at all. All updates should be asynchronous with the thread, not synchronous which is what you are tyring to do here. I would not even bother to attempt to debug this code. I'd rewrite it first. After that, you probably won't have the bugs.

Well, lengthy operations can be put in threads and executed at the same time for speed increase of a multiprocessor machine (like I have). Then you would want to continue when that processing ends. Anyway, screw that. Thanks for the information. I rewrote the code, but as I am playing with fire and still haven't learned how to control it correctly, there's still a deadlock. Here is the refined code:

template<typename T>
    void AddFilesThread(T* pFilesArg)
 {
     pp<UINT> pProgress = new UINT[si.dwNumberOfProcessors];
     vector<CString>* pFiles = (vector<CString>*)pFilesArg;
        EnumValuesArray* pFilesReg = (EnumValuesArray*)pFilesArg;
     DWORD dwSize;
     
      // Beware that size() returns the element count; NOT the highest index (which is count - 1)!
      if ( typeid(pFilesArg) == typeid(vector<CString>*) ) dwSize = (DWORD)pFiles->size() - 1;
     else if ( typeid(pFilesArg) == typeid(EnumValuesArray*) ) dwSize = (DWORD)pFilesReg->size() - 1;

     m_Tree.LockUpdate();
      ProgressDlg.ShowWindow(SW_SHOW);
      ZeroMemory(pProgress.GetPointer(), sizeof(*pProgress) * si.dwNumberOfProcessors);

       m_AddFilesCmd.EnableWindow(FALSE);
        m_StartEncodingCmd.EnableWindow(FALSE);
       m_StopEncodingCmd.EnableWindow(FALSE);
        m_RemoveFileCmd.EnableWindow(FALSE);

        NewThread(&CKantanAnimeDlg::AddFilesThread2<T>, this, pFilesArg, /*pCancel, */pProgress, dwSize);
   }

   template<typename T> void AddFilesThread2(T* pFilesArg, /*pp<bool> pCancel, */pp<UINT> pProgress, DWORD dwSize)
 {
     vector<CString>* pFiles = (vector<CString>*)pFilesArg;
        EnumValuesArray* pFilesReg = (EnumValuesArray*)pFilesArg;

       UINT nTotalProgress;
      UINT nLength = si.dwNumberOfProcessors;
       int nCount = 1;

     #pragma omp parallel private(pFiles, pFilesReg) shared(pProgress, dwSize)
     {
         CString strTemp;
          pFiles = (vector<CString>*)pFilesArg;
           pFilesReg = (EnumValuesArray*)pFilesArg;
          size_t nToExecute;

          if ( (omp_get_thread_num() + 1) == omp_get_num_threads() )
            {
             // Make sure that the last thread gets the remaining job until the end if an aneven number was divided
                nToExecute = (size_t)dwSize - ( dwSize / omp_get_num_threads() );
         }
         else
              nToExecute = (size_t)dwSize / omp_get_num_threads();

            for (size_t i = nToExecute * omp_get_thread_num(); nToExecute; i++, nToExecute--)
         {
             // Add file
               if ( typeid(pFilesArg) == typeid(vector<CString>*) )
                {
                 if (! AddNewFile(pFiles->at(i), GetFile( pFiles->at(i) ), true, true) )
                     MsgBox(this, "Failed to add new file...\n\n" + pFiles->at(i) + "\n\n...to the list!", ERR);
                }
             else if ( typeid(pFilesArg) == typeid(EnumValuesArray*) )
             {
                 if (! AddNewFile((char*)pFilesReg->at(i)->GetData(), GetFile( (char*)pFilesReg->at(i)->GetData() ), true, true) )
                     MsgBox(this, "Failed to add new file...\n\n" + (CString)(char*)pFilesReg->at(i)->GetData() + "\n\n...to the list!", ERR);
               }
                 
              // Update progress
                pProgress[ omp_get_thread_num() ]++;
              nTotalProgress = 0;
               for (UINT i = 0; i < nLength; i++) nTotalProgress += pProgress[i];
             ProgressDlg.m_ProgressText->Format("Loading encoding list. Please wait...\nAdding file %u of %u...", nTotalProgress, dwSize);
              ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::CALL_SETPOS, &ProgressDlg.m_Progress, (int)( (float)nTotalProgress / dwSize * 100 )) ) );

              if (nCount++ == 20) // Update for every 20 loops
              {
                 ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::CALL_UPDATEDATA, &ProgressDlg, FALSE) ) );
                   nCount = 1;
               }

               DoTasks(false);
               if (ProgressDlg.bCancel) break;
           }
     }

       ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::UNLOCK_TREE) ) );
        ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::CALL_SHOWWINDOW, &ProgressDlg, SW_HIDE) ) ); // DEADLOCK!
        ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::CALL_ENABLEWINDOW, &m_AddFilesCmd, FALSE) ) );
       ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::CALL_ENABLEWINDOW, &m_StartEncodingCmd, FALSE) ) );
      ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::CALL_ENABLEWINDOW, &m_StopEncodingCmd, FALSE) ) );
       ACCESS( m_GUITasks, m_GUITasks->push_back( new CGUITask(CGUITask::CALL_ENABLEWINDOW, &m_RemoveFileCmd, FALSE) ) );
     DoTasks(false);
   }

ACCESS is a macro that locks, does the expression, unlocks, to synchronize access to the m_GUITasks vector which stores all the commands for GUI update that the main thread will handle. DoTasks send a message (using PostThread) to the main window's window proc to tell it to process the GUI updates. As you can see above, however, the hiding of the progress window STILL causes a deadlock. And yes, the deadlock occurs in the window proc of the main window, which does the call.

Define "high level application". Messages are sent to windows. You get to choose which window it goes to. If you want to send a message to the top-level window of the application, feel free to do so.

Note that you can *only* send messages to windows. You cannot send user-defined messages to CDocuments, CWinApps, etc. Only WM_COMMAND messages can be handled by these non-window objects, and there's heavy-duty magic in MFC to make this so.

You cannot send user-defined messages to CDocuments, CWinApps, etc.

thanks for the quick reply. I had a need to send a message from a modeless dialog to my CWinApp derived class - no doubt deriving from a bad design choice. Looks like I'll need to rethink / maybe do a bit of redesign.

Mike

Dear NYT - the fact is, the founding fathers hung traitors.

See my essay on the use of I/O Completion Ports for queueing. While it doesn't send a message, it certainly does get messages to CWinApp. Note that you will also need to have a timer to keep the OnIdle active.

joe

See my essay on the use of I/O Completion Ports for queueing

thanks!

Mike

Dear NYT - the fact is, the founding fathers hung traitors.

First of all; thanks for an excellent article!

I'm using PostMessage and heap-allocated strings to add stuff to a listbox in my main thread. The memory is freed when the message is handled in the main window, but...

If I close the window, the thread terminates (correctly) and the posted messages are NOT handled since the window has been destroyed (WM_DESTROY comes before my posted messages?). I guess I need to explicitly handle all messages in the queue in OnDestroy.

How do I do that?

/Chris

Last thing in OnDestroy():

MSG msg;

while (PeekMessage(&msg, m_hWnd, UWM_ADDSTRING, UWM_ADDSTRING, PM_REMOVE) > 0)

{

DispatchMessage(&msg);

}

Voilà! =)

Maybe this should be pointed out in the article?

I was having a heck of a time trying to figure out how to get a process to update a progress bar in its parent dialog box. Thanks to your articles here on message management and threading, I was able to get it working.

As a non-professional progammer (I'm a psychologist), I appreciate the fact that folks like you post articles such as these.

Nick

I write a DLL for a Extended Procedure Stored and In SQL Server 2000 I used the DLL .when a Table in SQL Server 2000 is updated,the trigger will use the the DLL and In DLL I want to send a message to a user-intece or a threador a procedure(a exe) I use the ::SendMessage() but unsuccesful, if I use ::SendMessage in a thread or procedure is succesful ,I use RegisterWindowMessage to register a message , so I want to ask How to send message in a DLL for Extended Procedure Stored to communicate with a thread or procedure?

Thank you very much!

I have never used SQL or Stored Procedures. So I can't give a lot of insight into this. However, two questions arise that could make a difference: (a) do you know the actual executable context in which the stored procedure is executed? Is it within your own address space? and (b) how are you determining the handle of the window to which you are doing the ::SendMessage? I suspect one or both of these will influence the phenomenon you see, but since I've never used Stored Procedures I can't answer (a) and you need to answer (b)


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-29962-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...