multithreading - Can't get MFC worker thread to pass hWnd or MDI window pointer to thread -


for reason passing hwnd or pointer of newly created mdi window cannot recasted original value in worker thread. i've tried creating thread app class, document class , view class. have same effect. i'm using global function worker thread. funny thing i'm using same code used same thing in mfc mdi in 1998 , worked great doesn't seem work now.

perhaps i'm not seeing problem. going on here? want simple, create new view window, capture it's hwnd , pass hwnd worker thread worker thread can send messages window print strings , forth. i'd launch thread document class. compiler vs2010 , it's being run in debug.

after reading this: http://msdn.microsoft.com/en-us/library/h14y172e%28v=vs.100%29.aspx, realize can't pass pointer view class around worker threads. i'm focusing on hwnds. in ontestconnect block, valid hwnd returned valid pointer new view window.

here's code (from app class):

struct threadparms {     hwnd hwndview;     int test;    }; 

(note, i've tried defining struct typedef , variable name, have same result)

uint starter( lpvoid pparms ) {     threadparms* pthreadparms = (threadparms* )pparms;      //this step shouldn't necesarry tried anyway.  should     //be able use pthreadparms->hwndview without casting.     //the hwnd value not come across valid.  valid before sending.     hwnd hwnd = (hwnd)pthreadparms->hwndview;      //the int comes across fine     int inum = pthreadparms->test;       chftappbview* pview = (chftappbview*) chftappbview::fromhandle(hwnd);       //this bombs debug error becuase pview ptr invalid (though      //valid before sending on      pview->sendmessage( id_file_print, 0, 0 );       return 0;  }  void chftappbapp::ontestconnect() {     threadparms* pthreadparms = new threadparms;       //create window      afxgetapp()->oncmdmsg( id_file_new, 0, null, null );       cmdiframewnd* pframe = (cmdiframewnd*)afxgetapp()->m_pmainwnd;      cmdichildwnd* pchild = (cmdichildwnd*)pframe->getactiveframe();      chftappbview* pview = (chftappbview*)pchild->getactiveview();       pthreadparms->hwndview = pview->m_hwnd;      pthreadparms->test = 10;       afxbeginthread( starter, pthreadparms ); } 

part 2

//create window afxgetapp()->oncmdmsg( id_file_new, 0, null, null );  cmdiframewnd* pframe = (cmdiframewnd*)afxgetapp()->m_pmainwnd; cmdichildwnd* pchild = (cmdichildwnd*)pframe->getactiveframe(); chftappbview* pview = (chftappbview*)pchild->getactiveview();  hwnd h = pview->m_hwnd; sendmessage( h, id_file_print, 0, 0 ); 

i'm trying determine if hwnd valid. pview valid. stepping through code , looking @ pointer stats in debugger watch shows helathy pointer references cview class. not return healthy hwnd. debugger watch says 'can't evaluate' hwnd memory address , says 'unused=0'. running past iswindow returns true, however. go figure. trying send cview message cview window handle gets ignored. why getavtiveview return valid pointer hwnd in class return garbage?

part 3

after more digging, turns out hwnd valid though hwnd variable displays 'unused=???' in watch window. assume it's valid because hwnd received in thread code matches hwnd attached pview pointer in main code. pview pointer hwnd taken valid because watch recognizes valid cview class pointer returning name of cview class represents. there still 2 problems however. 1 though system sends valid hwnd cview window (pview->m_hwnd), sendmessage(pview->m_hwnd, id_file_print_preview, 0, 0,) refuses work. system ignores it. expected fileprintpreview command in newly created view window run. second fromhandle returns cwnd object , casting cview fails using of these methods:

uint threadtest1( lpvoid pparms ) {     threadparms* pthreadparms = (threadparms* )pparms;      //returns cwnd though handle valid cview      chftappbview* pview2 = (chftappbview*) chftappbview::fromhandle(hwnd);      //doesn't seem anything.  still returns hwnd system recognizes      //a cwnd.  that's reports in watch window.     chftappbview* pview = reinterpret_cast<chftappbview*>(chftappbview::fromhandle(hwnd));      //doesn't appear     dynamic_downcast( chftappbview, pview2 );      //confirms watch window says -- it's cwnd not cview.     if ( !pview->iskindof( runtime_class(chftappbview) ) )           afxmessagebox( "not cview" );      ::sendmessage( hwnd, id_file_print, 0, 0 );      return 0;  }  void chftappbdoc::main() {     afxgetapp()->oncmdmsg( id_file_new, 0, null, null );      threadparms* pthreadparms = new threadparms;      cmdiframewnd* pframe = (cmdiframewnd*)afxgetapp()->m_pmainwnd;     cmdichildwnd* pchild = (cmdichildwnd*)pframe->getactiveframe();     chftappbview* pview = (chftappbview*)pchild->getactiveview();      pthreadparms->hwndview = pview->m_hwnd;       afxbeginthread( threadtest1, pthreadparms );      sendmessage( pview->m_hwnd, id_file_print, 0, 0 );     //or     ::sendmessage( pview->m_hwnd, id_file_print, 0, 0 );   } 

so questions how can hwnd converted correct window pointer in thread code? why can't system cast cview?

part 4

probem solved (for now). lessons:

  1. cannot pass cview window pointer worker thread. see link above this.
  2. use sendmessage communicate between theads , windows

    //this works worker thread now

    threadparms* pthreadparms = (threadparms* )pparms;

    hwnd hwnd = static_cast(pthreadparms->hwndview);

    lresult lrst = ::sendmessage( pthreadparms->hwnd, wm_ggg, 0, 0 );

    //or just

    lresult lrst = ::sendmessage( pthreadparms->hwnd, wm_ggg, 0, 0 );

    //as cdoc method creates thread:

    chftappbview* pview = (chftappbview*)pchild->getactiveview();

    lresult lrst = ::sendmessage( pview->m_hwnd, wm_ggg, 0, 0 );

    cview's message map...

    on_message( wm_ggg, kk )

  3. pass hwnds worker threads identify cview windows

  4. cannot cast cwnd lower derrived class (and excpet work right).
  5. use on_message in view's message map capture commands sent sendmessage (be sure include method declaraion afx_msg in view's .h file)

all pretty straight forward looking answers (when faced myriad of possible causes) summary may help...

i still don't undertstand why casting fromhandle cview worked in old mfc app , not now. perhaps has code located. in old mfc app located in cview window , in code in cdoc class. cdocument not derrived cwnd cview is.

anyway, wraps problem up. big thank offered advice -- nik, scott, ulrich , mark. sage advice helpful.

you can call chftappbview::fromhandle(hwnd) isn't pointer chftappbview; it's pointer cwnd. casting it, you're telling compiler "trust me, pointer chftappbview. except isn't , shouldn't treat such or pretend is.

after all, if recipe calls orange juice, don't take lemon, paint orange, juice , call orange juice. you?

so do? well, if want send id_file_print message, don't need cwnd such. just do:

::sendmessage(hwnd, id_file_print, 0, 0); 

of course, that's also wrong. meant this:

::sendmessage(hwnd, wm_command, id_file_print, 0); 

update:

again, cannot trying do. let's go step step, shall we?

//returns cwnd though handle valid cview  chftappbview* pview2 = (chftappbview*) chftappbview::fromhandle(hwnd); 

right. cwnd::fromhandle returns pointer cwnd, not else. not giving pointer original chftappbview. it's giving new cwnd attached same hwnd. not valid cast chftappbview because new cwnd not chftappbview.

//doesn't seem anything.  still returns hwnd system recognizes  //a cwnd.  that's reports in watch window. chftappbview* pview = reinterpret_cast<chftappbview*>(chftappbview::fromhandle(hwnd)); 

again, cwnd::fromhandle returns pointer new cwnd knows nothing chftappbview. telling compiler "trust me, pointer chftappbview object!" except not. pointer cwnd attached hwnd chftappbview.

//doesn't appear dynamic_downcast( chftappbview, pview ); 

this still wouldn't anything. first of all, dynamic_downcast returns pointer chftappbview right there, you're calling mfc rtti functions not doing result. if did save result, wouldn't help. trying convert generic cwnd not.

i'll try explain 1 more time: when create view, mfc creates chftappbview object associated hwnd of view. when call cwnd::fromhandle passing in hwnd of view, mfc creates new , distinct cwnd instance points same hwnd - second cwnd not chftappbview , hwnd knows nothing mfc classes, views, documents or else.

you trying take cwnd * cwnd::fromhandle returns , hammer chftappbview *. no matter how hard try, not work. can ever cwnd * , nothing else.

as sidenote, cannot pass mfc objects 1 thread another, passing original chftappbview * cause weird issues crop up, , may lead hard track errors.

update 2:

you ask "why can't cwnd object cast window class derrives cwnd?"

let's start cwnd::fromhandle shall we?

cwnd* pascal cwnd::fromhandle(hwnd hwnd) {     chandlemap* pmap = afxmaphwnd(true); //create map if not exist     assert(pmap != null);     cwnd* pwnd = (cwnd*)pmap->fromhandle(hwnd);  #ifndef _afx_no_occ_support     pwnd->attachcontrolsite(pmap); #endif      assert(pwnd == null || pwnd->m_hwnd == hwnd);     return pwnd; } 

this leads chandlemap::fromhandle. code bit complicated , posting here won't help, let's not clutter things up. here function does, conceptually:

if handle found in map, returns it; otherwise, creates new cwnd , makes cwnd point hwnd passed in. returns pointer cwnd you. notice, only cwnd. nothiong else. see, cannot convert returned cwnd else - if else derived cwnd - because have cwnd , nothing more.

let's have wife. beautiful , love much. carry picture of in wallet. now, when meet , ask if married, take out wallet , proudly show them picture. person you're talking doesn't think married picture. , don't think can magically "convert" picture wife.

the situation here similar. cwnd::fromhandle gives "picture" of sorts. it's showing around, not else. asking "why can't transform picture wife?" answer because that's not how pictures work.


Comments

Popular posts from this blog

blackberry 10 - how to add multiple markers on the google map just by url? -

php - guestbook returning database data to flash -

delphi - Dynamic file type icon -