c++ - Create a form within a new Desktop using CreateDesktop/SwitchDesktop -


i need create system modal form utility should block entire windows until values entered. i'm experimenting creating desktops , switching. far, creating desktop switching it, , going works fine me.

but, when try create form, within new thread, form not show application keeps in newly created blank desktop, therefore blocking screen forever until logoff.

i made based in code found here:

http://developex.com/blog/system-modal-back/

// screenlocker.h  #pragma once  using namespace system; using namespace system::windows::forms;  namespace developex {    public ref class screenlocker    {    private:       string ^_desktopname;       form ^_form;       void dialogthread(void);     public:       static void showsystemmodaldialog (string ^desktopname, form ^form);    }; }   // screenlocker.cpp  #include "stdafx.h" #include "screenlocker.h"  using namespace system::threading; using namespace system::runtime::interopservices;  namespace developex {    void screenlocker::dialogthread()    {       // save handle current desktop       hdesk hdeskold = getthreaddesktop(getcurrentthreadid());        // create new desktop       intptr ptr = marshal::stringtohglobaluni(_desktopname);       hdesk hdesk = createdesktop((lpcwstr)ptr.topointer(),          null, null, 0, generic_all, null);        marshal::freehglobal(ptr);        // switch new deskop       switchdesktop(hdesk);        // assign new desktop current thread       setthreaddesktop(hdesk);        // run dialog       application::run(_form);        // switch initial desktop       switchdesktop(hdeskold);       closedesktop(hdesk);    }     void screenlocker::showsystemmodaldialog(string ^desktopname, form ^form)    {      // create , init screenlocker instance       screenlocker ^locker = gcnew screenlocker();       locker->_desktopname = desktopname;       locker->_form = form;        // create new thread dialog       (gcnew thread(gcnew threadstart(locker,          &developex::screenlocker::dialogthread)))->start();    } } 

well, i'm trying "translate" delphi , far have:

unit utils;  interface  uses   windows, messages, sysutils, variants, classes, graphics, controls, forms,   dialogs, stdctrls, adodb, grids, dbgrids, extctrls, comctrls, syncobjs, shellapi,   addtimeu;  type   tformshowthread = class(tthread)     hdesktopglobal: hdesk;     hdeskold: hdesk;      uheapsize: ulong;     tempdword: dword;      frm : tfrmblockscreen;   private   protected     procedure execute; override;   public     constructor create(form : tfrmblockscreen);     destructor destroy; override;   end;  implementation  constructor tformshowthread.create(form : tfrmblockscreen); begin   freeonterminate := true;   inherited create(true);   frm := form; end;   destructor tformshowthread.destroy; begin   inherited; end;  procedure tformshowthread.execute; begin     hdeskold := getthreaddesktop(getcurrentthreadid());      hdesktopglobal := createdesktop('z', nil, nil, 0, generic_all, nil);      switchdesktop(hdesktopglobal);     setthreaddesktop(hdesktopglobal);      // tried     application.createform(tfrmblockscreen, frm);      // tried same result     //frm := tfrmblockscreen.create(nil);     //frm.show();      switchdesktop(hdeskold);      closedesktop(hdesktopglobal); end;  end. 

i'm running code:

var   frmblockscreen : tfrmblockscreen;   frmshowthread : tformshowthread; begin    frmshowthread := tformshowthread.create(frmblockscreen);   frmshowthread.priority := tpnormal;   frmshowthread.onterminate := threaddone;   frmshowthread.start(); 

i don't understand why not work , c++, supposedly should work, creates new form within same application.

this how ended doing it:

i moved form wanted show, new project , compiled timeup.exe. created process procedure shown below, sending desktop parameter can assign process desktop. way didn't needed create new thread... it's working far.

there flaw in this?

var   hdesktopglobal: hdesk;   hdeskold: hdesk;    sdesktopname : string; begin   application.initialize;   application.mainformontaskbar := true;    try     hdeskold := getthreaddesktop(getcurrentthreadid());      sdesktopname := 'timeupdesktop';      hdesktopglobal := createdesktop(pwidechar(sdesktopname), nil, nil, 0, generic_all, nil);      switchdesktop(hdesktopglobal);     setthreaddesktop(hdesktopglobal);      execnewprocess('timeup.exe', sdesktopname);      switchdesktop(hdeskold);     closedesktop(hdesktopglobal);        switchdesktop(hdeskold);     closedesktop(hdesktopglobal);   end;    application.run; end.    procedure execnewprocess(programname : string; desktop : string); var   startinfo  : tstartupinfo;   procinfo   : tprocessinformation;   createok   : boolean; begin    { fill known state }   fillchar(startinfo,sizeof(tstartupinfo),#0);   fillchar(procinfo,sizeof(tprocessinformation),#0);   startinfo.cb := sizeof(tstartupinfo);   startinfo.lpdesktop := pchar(desktop);    createok := createprocess(pchar(programname),nil, nil, nil,false,               create_new_process_group+normal_priority_class,               nil, nil, startinfo, procinfo);    { check see if successful }   if createok     //may or may not needed. wait child processes     waitforsingleobject(procinfo.hprocess, infinite); end; 

before go further need recognise vcl design forces vcl forms associated main gui thread. cannot create them on different thread. design fundamentally flawed in way. never going able create vcl forms in thread other main gui thread.

even if not case, code not useful. that's because thread not contain message loop. no sooner has form been created, thread associated terminates.

you make work raw win32 calls createwindow etc. you'd need @ least run message loop in thread lifetime of windows created there.

as why code never switches original desktop, cannot sure. perhaps there exception in code attempts create form , code restores original desktop never runs. code should protected try/finally.

as general point, in order debug code calls raw win32 apis, must include error checking. don't any, , don't know api call failing. first step debugging problem this, if didn't know approach doomed failure no matter what.


perhaps i'm missing something, it's not obvious me why trying run form out of different thread. there reason why cannot run out of main gui thread?

and answer own question, missing something. documentation of setthreaddesktop:

the setthreaddesktop function fail if calling thread has windows or hooks on current desktop (unless hdesktop parameter handle current desktop).


Comments

Popular posts from this blog

linux - Does gcc have any options to add version info in ELF binary file? -

android - send complex objects as post php java -

charts - What graph/dashboard product is facebook using in Dashboard: PUE & WUE -