posts - 43,comments - 3,trackbacks - 0

Sending   Data   with   Messages  
  In   this   section,   we'll   examine   how   the   system   transfers   data   between   processes   using   window   messages.   Some   window   messages   specify   the   address   of   a   block   of   memory   in   their   lParam   parameter. For   example,   the   WM_SETTEXT   message   uses   the   lParam   parameter   as   a   pointer   to   a   zero-terminated   string   that   identifies   the   new   text   for   the   window.   Consider   the   following   call:  
   
  SendMessage(FindWindow(NULL,   "Calculator"),   WM_SETTEXT,  
        0,   (LPARAM)   "A   Test   Caption");   
    
        
  This   call   seems   harmless   enough—it   determines   the   window   handle   of   the   Calculator   application's   window   and   attempts   to   change   its   caption   to   A   Test   Caption.   But   let's   take   a   closer   look   at   what   happens   here.  
   
  The   string   of   the   new   title   is   contained   in   your   process's   address   space.   So   the   address   of   this   string   in   your   process   space   will   be   passed   as   the   lParam   parameter.   When   the   window   procedure   for   Calculator's   window   receives   this   message,   it   looks   at   the   lParam   parameter   and   attempts   to   manipulate   what   it   thinks   is   a   zero-terminated   string   in   order   to   make   it   the   new   title.  
   
  But   the   address   in   lParam   points   to   a   string   in   your   process's   address   space—not   in   Calculator's   address   space.   This   is   a   big   problem   because   a   memory   access   violation   is   sure   to   occur.   But   if   you   execute   the   line   above,   you'll   see   that   it   works   successfully.   How   can   this   be?  
   
  The   answer   is   that   the   system   looks   specifically   for   the   WM_SETTEXT   message   and   handles   it   differently   from   the   way   it   handles   most   other   messages.   When   you   call   SendMessage,   the   code   in   the   function   checks   whether   you   are   trying   to   send   a   WM_SETTEXT   message.   If   you   are,   it   packs   the   zero-terminated   string   from   your   address   space   into   a   memory-mapped   file   that   it   is   going   to   share   with   the   other   process.   Then   it   sends   the   message   to   the   thread   in   the   other   process.   When   the   receiving   thread   is   ready   to   process   the   WM_SETTEXT   message,   it   determines   the   location,   in   its   own   address   space,   of   the   shared   memory-mapped   file   that   contains   a   copy   of   the   new   window   text.   The   lParam   parameter   is   initialized   to   point   to   this   address,   and   the   WM_SETTEXT   message   is   dispatched   to   the   appropriate   window   procedure.   After   the   message   is   processed,   the   memory-mapped   file   is   destroyed.   Boy,   doesn't   this   seem   like   a   lot   of   work?  
   
  Fortunately,   most   messages   don't   require   this   type   of   processing—it   takes   place   only   when   an   application   sends   interprocess   messages.   Special   processing   such   as   this   has   to   be   performed   for   any   message   whose   wParam   or   lParam   parameters   represent   a   pointer   to   a   data   structure.  
   
  Let's   look   at   another   case   that   requires   special   handling   by   the   system—the   WM_GETTEXT   message.   Suppose   your   application   contains   the   following   code:  
   
  char   szBuf[200];  
  SendMessage(FindWindow(NULL,   "Calculator"),   WM_GETTEXT,  
        sizeof(szBuf),   (LPARAM)   szBuf);   
        
  The   WM_GETTEXT   message   requests   that   Calculator's   window   procedure   fill   the   buffer   pointed   to   by   szBuf   with   the   title   of   its   window.   When   you   send   this   message   to   a   window   in   another   process,   the   system   must   actually   send   two   messages.   First   the   system   sends   a   WM_GETTEXTLENGTH   message   to   the   window.   The   window   procedure   responds   by   returning   the   number   of   characters   required   to   hold   the   window's   title.   The   system   can   use   this   count   to   create   a   memory-mapped   file   that   will   end   up   being   shared   between   the   two   processes.  
   
  Once   the   memory-mapped   file   has   been   created,   the   system   can   send   the   WM_GETTEXT   message   to   fill   it.   Then   the   system   switches   back   to   the   process   that   called   SendMessage   in   the   first   place,   copies   the   data   from   the   shared   memory-mapped   file   into   the   buffer   pointed   to   by   szBuf,   and   returns   from   the   call   to   SendMessage.  
   
  Well,   all   this   is   fine   and   good   if   you   are   sending   messages   that   the   system   is   aware   of.   But   what   if   you   create   your   own   (WM_USER   +   x)   message   that   you   want   to   send   from   one   process   to   a   window   in   another?   The   system   will   not   know   that   you   want   it   to   use   memory-mapped   files   and   to   update   pointers   when   sending.   However,   Microsoft   has   created   a   special   window   message,   WM_COPYDATA,   for   exactly   this   purpose:  
   
  COPYDATASTRUCT   cds;  
  SendMessage(hwndReceiver,   WM_COPYDATA,  
        (WPARAM)   hwndSender,   (LPARAM)   &cds);   
   
  COPYDATASTRUCT   is   a   structure   defined   in   WinUser.h,   and   it   looks   like   this:  
   
  typedef   struct   tagCOPYDATASTRUCT   {  
        ULONG_PTR   dwData;  
        DWORD   cbData;  
        PVOID   lpData;  
  }   COPYDATASTRUCT;   
    
       When   you're   ready   to   send   some   data   to   a   window   in   another   process,   you   must   first   initialize   the   COPYDATASTRUCT   structure.   The   dwData   member   is   reserved   for   your   own   use.   You   can   place   any   value   in   it.   For   example,   you   might   have   occasion   to   send   different   types   or   categories   of   data   to   the   other   process.   You   can   use   this   value   to   indicate   the   content   of   the   data   you   are   sending.  
   
  The   cbData   member   specifies   the   number   of   bytes   that   you   want   to   transfer   to   the   other   process,   and   the   lpData   member   points   to   the   first   byte   of   the   data.   The   address   pointed   to   by   lpData   is,   of   course,   in   the   sender's   address   space.  
   
  When   SendMessage   sees   that   you   are   sending   a   WM_COPYDATA   message,   it   creates   a   memory-mapped   file   cbData   bytes   in   size   and   copies   the   data   from   your   address   space   to   the   memory-mapped   file.   It   then   sends   the   message   to   the   destination   window.   When   the   receiving   window   procedure   processes   this   message,   the   lParam   parameter   points   to   a   COPYDATASTRUCT   that   exists   in   the   address   space   of   the   receiving   process.   The   lpData   member   of   this   structure   points   to   the   view   of   the   shared   memory-mapped   file   in   the   receiving   process's   address   space.  
   
  You   should   remember   three   important   things   about   the   WM_COPYDATA   message:   
        
  Always   send   this   message;   never   post   it.   You   can't   post   a   WM_COPYDATA   message   because   the   system   must   free   the   memory-mapped   file   after   the   receiving   window   procedure   has   processed   the   message.   If   you   post   the   message,   the   system   doesn't   know   when   the   WM_COPYDATA   message   is   processed,   and   therefore   it   can't   free   the   copied   block   of   memory.  
   
   
  It   takes   some   time   for   the   system   to   make   a   copy   of   the   data   in   the   other   process's   address   space.   This   means   that   you   shouldn't   have   another   thread   that   modifies   the   contents   of   the   memory   block   running   in   the   sending   application   until   the   call   to   SendMessage   returns.  
   
   
  The   WM_COPYDATA   message   allows   a   16-bit   application   to   communicate   with   a   32-bit   application   and   vice   versa.   It   also   allows   a   32-bit   application   to   talk   to   a   64-bit   application   and   vice   versa.   This   is   an   incredibly   easy   way   to   have   newer   applications   talk   to   older   applications.   Also   note   that   WM_COPYDATA   is   fully   supported   on   Windows   2000   and   Windows   98.   Unfortunately,   if   you   are   still   writing   16-bit   Windows   applications,   Microsoft   Visual   C++   1.52   does   not   have   a   definition   for   the   WM_COPYDATA   message   or   the   COPYDATASTRUCT   structure.   You   will   need   to   add   them   manually:  
   
  //   Manually   include   this   in   your   16-bit   Windows   source   code.  
  #define   WM_COPYDATA       0x004A  
   
  typedef   VOID   FAR*   PVOID;  
  typedef   struct   tagCOPYDATASTRUCT   {  
        DWORD   dwData;  
        DWORD   cbData;  
        PVOID   lpData;  
  }   COPYDATASTRUCT,   FAR*   PCOPYDATASTRUCT;     
        
  The   WM_COPYDATA   message   is   an   incredible   device   that   could   save   many   developers   hours   of   time   when   trying   to   solve   interprocess   communication   problems.   It's   a   shame   it's   not   used   more   frequently.  
    
    Sending   Messages   to   a   Window  
  Window   messages   can   be   sent   directly   to   a   window   procedure   by   using   the   SendMessage   function:  
   
  LRESULT   SendMessage(  
        HWND   hwnd,    
        UINT   uMsg,    
        WPARAM   wParam,  
        LPARAM   lParam);   
    
  The   window   procedure   will   process   the   message.   Only   after   the   message   has   been   processed   will   SendMessage   return   to   the   caller.   Because   of   its   synchronous   nature,   SendMessage   is   used   more   frequently   than   either   PostMessage   or   PostThreadMessage.   The   calling   thread   knows   that   the   window   message   has   been   completely   processed   before   the   next   line   of   code   executes.  
   
  Here   is   how   SendMessage   works.   If   the   thread   calling   SendMessage   is   sending   a   message   to   a   window   created   by   the   same   thread,   SendMessage   is   simple:   it   just   calls   the   specified   window's   window   procedure   as   a   subroutine.   When   the   window   procedure   is   finished   processing   the   message,   it   returns   a   value   back   to   SendMessage.   SendMessage   returns   this   value   to   the   calling   thread.  
   
  However,   if   a   thread   is   sending   a   message   to   a   window   created   by   another   thread,   the   internal   workings   of   SendMessage   are   far   more   complicated.1   Windows   requires   that   the   thread   that   created   the   window   process   the   window's   message.   So   if   you   call   SendMessage   to   send   a   message   to   a   window   created   by   another   process,   and   therefore   to   another   thread,   your   thread   cannot   possibly   process   the   window   message   because   your   thread   is   not   running   in   the   other   process's   address   space   and   therefore   does   not   have   access   to   the   window   procedure's   code   and   data.   In   fact,   your   thread   is   suspended   while   the   other   thread   is   processing   the   message.   So   in   order   to   send   a   window   message   to   a   window   created   by   another   thread,   the   system   must   perform   the   actions   I'll   discuss   next.  
   
  First,   the   sent   message   is   appended   to   the   receiving   thread's   send-message   queue,   which   has   the   effect   of   setting   the   QS_SENDMESSAGE   flag   (which   I'll   discuss   later)   for   that   thread.   Second,   if   the   receiving   thread   is   already   executing   code   and   isn't   waiting   for   messages   (on   a   call   to   GetMessage,   PeekMessage,   or   WaitMessage),   the   sent   message   can't   be   processed—the   system   won't   interrupt   the   thread   to   process   the   message   immediately.   When   the   receiving   thread   is   waiting   for   messages,   the   system   first   checks   to   see   whether   the   QS_SENDMESSAGE   wake   flag   is   set,   and   if   it   is,   the   system   scans   the   list   of   messages   in   the   send-message   queue   to   find   the   first   sent   message.   It   is   possible   that   several   sent   messages   could   pile   up   in   this   queue.   For   example,   several   threads   could   each   send   a   message   to   a   single   window   at   the   same   time.   When   this   happens,   the   system   simply   appends   these   messages   to   the   receiving   thread's   send-message   queue.  
   
  When   the   receiving   thread   is   waiting   for   messages,   the   system   extracts   the   first   message   in   the   send-message   queue   and   calls   the   appropriate   window   procedure   to   process   the   message.   If   no   more   messages   are   in   the   send-message   queue,   the   QS_SENDMESSAGE   wake   flag   is   turned   off.   While   the   receiving   thread   is   processing   the   message,   the   thread   that   called   SendMessage   is   sitting   idle,   waiting   for   a   message   to   appear   in   its   reply-message   queue.   After   the   sent   message   is   processed,   the   window   procedure's   return   value   is   posted   to   the   sending   thread's   reply-message   queue.   The   sending   thread   will   now   wake   up   and   retrieve   the   return   value   contained   inside   the   reply   message.   This   return   value   is   the   value   that   is   returned   from   the   call   to   SendMessage.   At   this   point,   the   sending   thread   continues   execution   as   normal.  
   
  While   a   thread   is   waiting   for   SendMessage   to   return,   it   basically   sits   idle.   It   is,   however,   allowed   to   perform   one   task:   if   another   thread   in   the   system   sends   a   message   to   a   window   created   by   a   thread   that   is   waiting   for   SendMessage   to   return,   the   system   will   process   the   sent   message   immediately.   The   system   doesn't   have   to   wait   for   the   thread   to   call   GetMessage,   PeekMessage,   or   WaitMessage   in   this   case.  
   
  Because   Windows   uses   this   method   to   handle   the   sending   of   interthread   messages,   it's   possible   that   your   thread   could   hang.   For   example,   let's   say   that   the   thread   processing   the   sent   message   has   a   bug   and   enters   an   infinite   loop.   What   happens   to   the   thread   that   called   SendMessage?   Will   it   ever   be   resumed?   Does   this   mean   that   a   bug   in   one   application   can   cause   another   application   to   hang?   The   answer   is   yes!  
   
  Four   functions—SendMessageTimeout,   SendMessageCallback,   SendNotifyMessage,   and   ReplyMessage—allow   you   to   write   code   defensively   to   protect   yourself   from   this   situation.   The   first   function   is   SendMessageTimeout:  
   
  LRESULT   SendMessageTimeout(  
        HWND   hwnd,    
        UINT   uMsg,    
        WPARAM   wParam,  
        LPARAM   lParam,    
        UINT   fuFlags,    
        UINT   uTimeout,    
        PDWORD_PTR   pdwResult);  
   
     
   
   
  The   SendMessageTimeout   function   allows   you   to   specify   the   maximum   amount   of   time   you   are   willing   to   wait   for   another   thread   to   reply   to   your   message.   The   first   four   parameters   are   the   same   parameters   that   you   pass   to   SendMessage.   For   the   fuFlags   parameter,   you   can   pass   SMTO_NORMAL   (defined   as   0),   SMTO_ABORTIFHUNG,   SMTO_BLOCK,   SMTO_NOTIMEOUTIFNOTHUNG,   or   a   combination   of   these   flags.  
   
  The   SMTO_ABORTIFHUNG   flag   tells   SendMessageTimeout   to   check   whether   the   receiving   thread   is   in   a   hung   state2   and,   if   so,   to   return   immediately.   The   SMTO_NOTIMEOUTIFNOTHUNG   flag   causes   the   function   to   ignore   the   timeout   value   if   the   receiving   thread   is   not   hung.   The   SMTO_BLOCK   flag   causes   the   calling   thread   not   to   process   any   other   sent   messages   until   SendMessageTimeout   returns.   The   SMTO_NORMAL   flag   is   defined   as   0   in   WinUser.h;   this   is   the   flag   to   use   if   you   don't   specify   any   combination   of   the   other   flags.  
   
  Earlier   in   this   section   I   said   that   a   thread   could   be   interrupted   while   waiting   for   a   sent   message   to   return   so   that   it   can   process   another   sent   message.   Using   the   SMTO_BLOCK   flag   stops   the   system   from   allowing   this   interruption.   You   should   use   this   flag   only   if   your   thread   could   not   process   a   sent   message   while   waiting   for   its   sent   message   to   be   processed.   Using   SMTO_BLOCK   could   create   a   deadlock   situation   until   the   timeout   expires—for   example,   if   you   send   a   message   to   another   thread   and   that   thread   needs   to   send   a   message   to   your   thread.   In   this   case,   neither   thread   can   continue   processing   and   both   threads   are   forever   suspended.  
   
  The   uTimeout   parameter   specifies   the   number   of   milliseconds   you   are   willing   to   wait   for   the   reply   message.   If   the   function   is   successful,   TRUE   is   returned   and   the   result   of   the   message   is   copied   into   the   buffer   whose   address   you   specify   in   the   pdwResult   parameter.  
   
  By   the   way,   this   function   is   prototyped   incorrectly   in   the   header   file   of   WinUser.h.   The   function   should   be   prototyped   simply   as   returning   a   BOOL   since   the   LRESULT   is   actually   returned   via   a   parameter   to   the   function.   This   raises   some   problems   because   SendMessageTimeout   will   return   FALSE   if   you   pass   an   invalid   window   handle   or   if   it   times   out.   The   only   way   to   know   for   sure   why   the   function   failed   is   by   calling   GetLastError.   However,   GetLastError   will   be   0   (ERROR_SUCCESS)   if   the   function   fails   because   of   a   timeout.   If   you   pass   an   invalid   handle,   GetLastError   will   be   1400   (ERROR_INVALID_WINDOW_HANDLE).  
   
  If   you   call   SendMessageTimeout   to   send   a   message   to   a   window   created   by   the   calling   thread,   the   system   simply   calls   the   window   procedure   and   places   the   return   value   in   pdwResult.   Because   all   processing   must   take   place   with   one   thread,   the   code   following   the   call   to   SendMessageTimeout   cannot   start   executing   until   after   the   message   has   been   processed.  
   
  The   second   function   that   can   help   send   interthread   messages   is   SendMessageCallback:  
   
  BOOL   SendMessageCallback(  
        HWND   hwnd,    
        UINT   uMsg,  
        WPARAM   wParam,  
        LPARAM   lParam,    
        SENDASYNCPROC   pfnResultCallBack,    
        ULONG_PTR   dwData);  
   
     
   
   
  Again,   the   first   four   parameters   are   the   same   as   those   used   by   the   SendMessage   function.   When   a   thread   calls   SendMessageCallback,   the   function   sends   the   message   off   to   the   receiving   thread's   send-message   queue   and   immediately   returns   so   that   your   thread   can   continue   processing.   When   the   receiving   thread   has   finished   processing   the   message,   a   message   is   posted   to   the   sending   thread's   reply-message   queue.   Later,   the   system   notifies   your   thread   of   the   reply   by   calling   a   function   that   you   write   using   the   following   prototype:  
   
  VOID   CALLBACK   ResultCallBack(  
        HWND   hwnd,    
        UINT   uMsg,    
        ULONG_PTR   dwData,  
        LRESULT   lResult);  
   
     
   
   
  You   must   pass   the   address   to   this   function   as   the   pfnResultCallBack   parameter   of   SendMessageCallback.   When   this   function   is   called,   it   is   passed   the   handle   of   the   window   that   finished   processing   the   message   and   the   message   value   in   the   first   two   parameters.   The   third   parameter,   dwData,   will   always   be   the   value   that   you   passed   in   the   dwData   parameter   to   SendMessageCallback.   The   system   simply   takes   whatever   you   specify   here   and   passes   it   directly   to   your   ResultCallBack   function.   The   last   parameter   passed   to   your   ResultCallBack   function   is   the   result   from   the   window   procedure   that   processed   the   message.  
   
  Because   SendMessageCallback   returns   immediately   when   performing   an   interthread   send,   the   callback   function   is   not   called   as   soon   as   the   receiving   thread   finishes   processing   the   message.   Instead,   the   receiving   thread   posts   a   message   to   the   sending   thread's   reply-message   queue.   The   next   time   the   sending   thread   calls   GetMessage,   PeekMessage,   WaitMessage,   or   one   of   the   SendMessage*   functions,   the   message   is   pulled   from   the   reply-message   queue   and   your   ResultCallBack   function   is   executed.  
   
  The   SendMessageCallback   function   has   another   use.   Windows   offers   a   method   by   which   you   can   broadcast   a   message   to   all   the   existing   overlapped   windows   in   the   system   by   calling   SendMessage   and   passing   HWND_BROADCAST   (defined   as   -1)   as   the   hwnd   parameter.   Use   this   method   only   to   broadcast   a   message   whose   return   value   you   aren't   interested   in,   because   the   function   can   return   only   a   single   LRESULT.   But   by   using   the   SendMessageCallback   function,   you   can   broadcast   a   message   to   every   overlapped   window   and   see   the   result   of   each.   Your   ResultCallBack   function   will   be   called   with   the   result   of   every   window   processing   the   message.  
   
  If   you   call   SendMessageCallback   to   send   a   message   to   a   window   created   by   the   calling   thread,   the   system   immediately   calls   the   window   procedure,   and   then,   after   the   message   is   processed,   the   system   calls   the   ResultCallBack   function.   After   the   ResultCallBack   function   returns,   execution   begins   at   the   line   following   the   call   to   SendMessageCallback.  
   
  The   third   function   that   can   help   send   interthread   messages   is   SendNotifyMessage:  
   
  BOOL   SendNotifyMessage(  
        HWND   hwnd,    
        UINT   uMsg,    
        WPARAM   wParam,  
        LPARAM   lParam);  
   
     
   
   
  SendNotifyMessage   places   a   message   in   the   send-message   queue   of   the   receiving   thread   and   returns   to   the   calling   thread   immediately.   This   should   sound   familiar   because   it   is   exactly   what   the   PostMessage   function   does.   However,   SendNotifyMessage   differs   from   PostMessage   in   two   ways.  
   
  First,   if   SendNotifyMessage   sends   a   message   to   a   window   created   by   another   thread,   the   sent   message   has   higher   priority   than   posted   messages   placed   in   the   receiving   thread's   queue.   In   other   words,   messages   that   the   SendNotifyMessage   function   places   in   a   queue   are   always   retrieved   before   messages   that   the   PostMessage   function   posts   to   a   queue.  
   
  Second,   when   you   are   sending   a   message   to   a   window   created   by   the   calling   thread,   SendNotifyMessage   works   exactly   like   the   SendMessage   function:   SendNotifyMessage   doesn't   return   until   the   message   has   been   processed.  
   
  As   it   turns   out,   most   messages   sent   to   a   window   are   used   for   notification   purposes;   that   is,   the   message   is   sent   because   the   window   needs   to   be   aware   that   a   state   change   has   occurred   so   that   it   can   perform   some   processing   before   you   carry   on   with   your   work.   For   example,   WM_ACTIVATE,   WM_DESTROY,   WM_ENABLE,   WM_SIZE,   WM_SETFOCUS,   and   WM_MOVE   (to   name   just   a   few)   are   all   notifications   that   are   sent   to   a   window   by   the   system   instead   of   being   posted.   However,   these   messages   are   notifications   to   the   window;   the   system   doesn't   have   to   stop   running   so   that   the   window   procedure   can   process   these   messages.   In   contrast,   when   the   system   sends   a   WM_CREATE   message   to   a   window,   the   system   must   wait   until   the   window   has   finished   processing   the   message.   If   the   return   value   is   -1,   the   window   is   not   created.  
   
  The   fourth   function   that   can   help   in   sending   interthread   messages   is   ReplyMessage:  
   
  BOOL   ReplyMessage(LRESULT   lResult);   
    
          
    
  This   function   is   different   from   the   three   functions   we   just   discussed.   Whereas   SendMessageTimeout,   SendMessageCallback,   and   SendNotifyMessage   are   used   by   the   thread   sending   a   message   to   protect   itself   from   hanging,   ReplyMessage   is   called   by   the   thread   receiving   the   window   message.   When   a   thread   calls   ReplyMessage,   it   is   telling   the   system   that   it   has   completed   enough   work   to   know   the   result   of   the   message   and   that   the   result   should   be   packaged   up   and   posted   to   the   sending   thread's   reply-message   queue.   This   allows   the   sending   thread   to   wake   up,   get   the   result,   and   continue   executing.  
   
  The   thread   calling   ReplyMessage   specifies   the   result   of   processing   the   message   in   the   lResult   parameter.   After   ReplyMessage   is   called,   the   thread   that   sent   the   message   resumes,   and   the   thread   processing   the   message   continues   to   process   the   message.   Neither   thread   is   suspended;   both   can   continue   executing   normally.   When   the   thread   processing   the   message   returns   from   its   window   procedure,   any   value   that   it   returns   is   simply   ignored.  
   
  The   problem   with   ReplyMessage   is   that   it   has   to   be   called   from   within   the   window   procedure   that   is   receiving   the   message   and   not   by   the   thread   that   called   one   of   the   Send*   functions.   So   you   are   better   off   writing   defensive   code   by   replacing   your   calls   to   SendMessage   with   one   of   the   three   Send*   functions   discussed   previously   instead   of   relying   on   the   implementer   of   a   window   procedure   to   make   calls   to   ReplyMessage.  
   
  You   should   also   be   aware   that   ReplyMessage   does   nothing   if   you   call   it   while   processing   a   message   sent   from   the   same   thread.   In   fact,   this   is   what   ReplyMessage's   return   value   indicates.   ReplyMessage   returns   TRUE   if   you   call   it   while   you   are   processing   an   interthread   send   and   FALSE   if   you   are   processing   an   intrathread   send.  
   
  At   times,   you   might   want   to   know   if   you   are   processing   an   interthread   or   an   intrathread   sent   message.   You   can   find   this   out   by   calling   InSendMessage:  
   
  BOOL   InSendMessage();  
   
     
   
   
  The   name   of   this   function   does   not   accurately   explain   what   it   does.   At   first   glance,   you   would   think   that   this   function   returns   TRUE   if   the   thread   is   processing   a   sent   message   and   FALSE   if   it's   processing   a   posted   message.   You   would   be   wrong.   The   function   returns   TRUE   if   the   thread   is   processing   an   interthread   sent   message   and   FALSE   if   it   is   processing   an   intrathread   sent   or   posted   message.   The   return   values   of   InSendMessage   and   ReplyMessage   are   identical.  
   
  There   is   another   function   that   you   can   call   to   determine   what   type   of   message   your   window   procedure   is   processing:  
   
  DWORD   InSendMessageEx(PVOID   pvReserved);     
    
         
    
  When   you   call   this   function,   you   must   pass   NULL   for   the   pvReserved   parameter.   The   function's   return   value   indicates   what   type   of   message   you   are   processing.   If   the   return   value   is   ISMEX_NOSEND   (defined   as   0),   the   thread   is   processing   an   intrathread   sent   or   posted   message.   If   the   return   value   is   not   ISMEX_NOSEND,   it   is   a   combination   of   the   bit   flags   described   in   the   following   table.  
   
  Flag   Description    
  ISMEX_SEND   The   thread   is   processing   an   interthread   sent   message   sent   using   either   the   SendMessage   or   SendMessageTimeout   function.   If   the   ISMEX_REPLIED   flag   is   not   set,   the   sending   thread   is   blocked   waiting   for   the   reply.    
  ISMEX_NOTIFY   The   thread   is   processing   an   interthread   sent   message   sent   using   the   SendNotifyMessage   function.   The   sending   thread   is   not   waiting   for   a   reply   and   is   not   blocked.    
  ISMEX_CALLBACK   The   thread   is   processing   an   interthread   sent   message   sent   using   the   SendMessageCallback   function.   The   sending   thread   is   not   waiting   for   a   reply   and   is   not   blocked.    
  ISMEX_REPLIED   The   thread   is   processing   an   interthread   sent   message   and   has   already   called   ReplyMessage.   The   sending   thread   is   not   blocked.

posted on 2010-05-08 23:30 RUI 阅读(2357) 评论(0)  编辑 收藏 引用 所属分类: Windows Programming

只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理