Results 1 to 15 of 15

Thread: form shared in two different executables (projects)

  1. #1

    Thread Starter
    Fanatic Member mutley's Avatar
    Join Date
    Apr 2000
    Location
    Sao Paulo - Brazil
    Posts
    709

    form shared in two different executables (projects)

    Hi


    I have a form that is shared by two projects, in one of them this form is the first to be instantiated (this project and form already existed), now there is another (new) project that should call this same form, but some fields should be and others not including including in a given table, there is a column that must be filled when called from the new project and must be null when called from the other (old) project

    Would you like to know a way of knowing when you are calling from the old project or the new project?
    In this case I have to include the form in the new project?

    Anyway I would like to know the best way to do this


    Tia

  2. #2
    Hyperactive Member
    Join Date
    Mar 2018
    Posts
    462

    Re: form shared in two different executables (projects)

    you can check the exe name of productname using the builtin "app" properties
    Code:
    if app.EXEName = "Project1" then
    
    else
    
    end if

  3. #3
    Addicted Member
    Join Date
    Jun 2018
    Posts
    189

    Re: form shared in two different executables (projects)

    If you actually intend sharing your form with two or more separate executable projects with code reuse and all, the best would be to include your form in a separate ActiveX DLL and create public methods to access the form appropriately. Then make reference to the compiled Ax-DLL within your std-Exe projects and call the methods in DLL appropriately.

  4. #4
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    14,206

    Re: form shared in two different executables (projects)

    I shared a few forms in more than one project in the past. Wasn't long before I decided it was not a good way to go and made copies of those forms for each project. The ones that were going to stay static I saved as templates and then just added them to future projects as needed.
    The two biggest issues I ran into when sharing forms or modules was 1: the location of the file which made it difficult to copy one of those projects to another location as it was easy to missed the shared files. and 2 if I needed to make a change to the code in one of these shared files it could have an adverse or unwanted effect on one or more other projects.

    In the end it made more sense to keep each project self contained and not use any code files that were shared and instead use copies of them as needed. Sure you can end up with multiple copies of the same exact file in different locations but that is not such a bad thing.

  5. #5
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,622

    Re: form shared in two different executables (projects)

    No offense intended...but WHY would you do this in the first place? Makes very little sense to me. Obviously possible (from post #4), but because the same information is not seen/used in both projects on the shared form, I would think the 'data' used to populate the form could be shared in a separate file (probably simple text file, or possibly a DB file). That file could be opened in both projects, and read differently to get the pertinent information for each project. In what I am thinking, each project would have its own form (although they may look similar). I don't know if the two projects will be run simultaneously or not (OP doesn't state). If so, I would assume issues could arise from sharing the form, as well as, sharing a text file (or even a database---although that could easily be solved). It would be nice to know what OP's form looks like, when potentially run from each project...and WHY this approach is considered.

  6. #6
    PowerPoster
    Join Date
    Feb 2012
    Location
    West Virginia
    Posts
    14,206

    Re: form shared in two different executables (projects)

    Well when I hear sharing a form what that says to me is that both projects are mapped to the same .frm file when compiled they are totally separate but in the code environment if a change is made to the form in one project it effects both and imo this is a gotcha waiting to happen.

  7. #7
    PowerPoster SamOscarBrown's Avatar
    Join Date
    Aug 2012
    Location
    NC, USA
    Posts
    9,622

    Re: form shared in two different executables (projects)

    imo this is a gotcha waiting to happen.
    ... and in mine, too!

  8. #8
    PowerPoster Elroy's Avatar
    Join Date
    Jun 2014
    Location
    Near Nashville TN
    Posts
    10,909

    Re: form shared in two different executables (projects)

    Well, I suppose I'll jump in here and outline my experience. I don't have any EXE projects where I share any forms. But that's possibly because I only have one EXE project to which I pay any real attention these days. I do have others, but they're mostly in the category of utilities, rather than production/distribution projects.

    Now, I do have 17 ActiveX DLL projects that hang off of that primary EXE project. And, those 17 DLL projects do have a folder that contains "shared" modules. There are actually 12 shared modules. I'll outline them:

    1 for a .manifest file.
    4 for BAS modules.
    3 for CTL modules.
    1 CLS module.
    3 FRM modules.

    (There are also some ..X modules, but I didn't count those.)

    So, directly related to this thread, it can be seen that I share three FRM modules. I'll outline those as well. Two of the FRM modules are directly related to CTL modules, and are never seen except when in the non-running mode in the IDE. They're for controls that show RTF text. One of those FRM files is for typing in RTF text while developing, and the other is for inserting pictures into the RTF text. So, I'm not sure those two FRM modules really count, since they're just "tag-alongs" to the CTL modules.

    The last FRM that's shared is used only for questionnaires (of which 10 of the 17 DLLs are). Here, I'll give a picture of it (this is in the IDE, it's borderless when running):

    Name:  Shared.png
Views: 528
Size:  3.7 KB

    So, here's the deal with that form. Most of the questionnaires have both English and Spanish versions. However, when in the Spanish version, there's a way to "pop-up" the English version on top of the Spanish question. This helps assistance help Spanish speaking people when the assistant may not know Spanish well. That above form is an always-on-top form and is just used to remind the assistant how to get back to the Spanish version. And again, that form is just shared among all 10 DLL questionnaires.

    So, bottom line ... for the most part, I've got to agree with the opinion that this is typically a bad idea. I would consider it only for the simplest of forms, as any complex form will probably eventually be customized for each specific project. Also, if you do share, you've got to be VERY careful if/when both projects might be loaded. In that situation, it would be extremely easy to start losing work.

    Maybe my experience will help.

    Good Luck,
    Elroy
    Any software I post in these forums written by me is provided "AS IS" without warranty of any kind, expressed or implied, and permission is hereby granted, free of charge and without restriction, to any person obtaining a copy. To all, peace and happiness.

  9. #9
    Member
    Join Date
    Apr 2014
    Posts
    40

    Re: form shared in two different executables (projects)

    An easy way is …. create not a Form but a UserControl !
    In each project who need the pseudo shared Form create an empty form containing the shared UserControl

    100% VB Compliant and simple…

    PS 15 years ago I did a professional projects, sharing not Forms but MDIChild Forms in sub projects (Dll ActiveX)…

  10. #10
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,538

    Re: form shared in two different executables (projects)

    vb6 how to getobject(**) by rot,List Rot ,GetRunningObjectTable
    can use rot to share forms object
    http://www.vbforums.com/showthread.p...ingObjectTable
    m_lCookie = PutObject(Me, "MySpecialProject.Form1")
    m_lCookie = PutObject(Me, "Project2.Form1")

    use createobject to share forms.
    Last edited by xiaoyao; Feb 9th, 2020 at 08:11 PM.

  11. #11

  12. #12
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,538

    Cool Re: form shared in two different executables (projects)

    Quote Originally Posted by The trick View Post
    To identify a COM object instance the COM uses monikers. You can use for example an ObjRef moniker to bind two executables.
    can you give me a vb6 samples for "ObjRef moniker",thank you

  13. #13
    PowerPoster
    Join Date
    Feb 2015
    Posts
    2,797

    Re: form shared in two different executables (projects)

    can you give me a vb6 samples for "ObjRef moniker",thank you
    This it the simple example of OBJRef moniker usage. If you run the host application you can run a child process. You can run either VB6 executable, C++ executable (64 bit) or HTA Script. Then you can just call the methods of the host application. Using such monikers you can connect your applications and just call the methods between processes (or even between machines).

    Host:
    Code:
    ' //
    ' // IPC using OBJRef moniker
    ' // Host app
    ' // by The trick 2020
    ' //
    
    Option Explicit
    
    Private Declare Function ShellExecute Lib "shell32.dll" _
                             Alias "ShellExecuteW" ( _
                             ByVal hwnd As Long, _
                             ByVal lpOperation As Long, _
                             ByVal lpFile As Long, _
                             ByVal lpParameters As Long, _
                             ByVal lpDirectory As Long, _
                             ByVal nShowCmd As Long) As Long
    
    Private m_bClientActive As Boolean
    
    Public Sub ClientDisconnect()
        
        m_bClientActive = False
        
        cmdRun64BitCppClient.Enabled = True
        cmdRunVB6Client.Enabled = True
        cmdRunScriptClient.Enabled = True
        
    End Sub
    
    Public Sub Kick( _
               ByRef sMsg As String)
        MsgBox sMsg, vbInformation, "Kicked!"
    End Sub
    
    Private Function RunClient( _
                     ByRef sPath As String) As Boolean
        Dim cMoniker    As IMoniker
        Dim pName       As Long
        Dim sName       As String
        Dim sCmdLine    As String
        
        On Error GoTo exit_proc
        
        Set cMoniker = CreateObjrefMoniker(Me)
        
        pName = cMoniker.GetDisplayName(CreateBindCtx(), Nothing)
        sName = SysAllocString(pName)
        
        CoGetMalloc(1).Free pName
        
        If ShellExecute(0, StrPtr("open"), StrPtr(sPath), StrPtr("""" & sName & """"), 0, vbNormalFocus) <= 32 Then
            Err.Raise 5
        End If
        
        m_bClientActive = True
        
        cmdRun64BitCppClient.Enabled = False
        cmdRunVB6Client.Enabled = False
        cmdRunScriptClient.Enabled = False
        
        RunClient = True
        
    exit_proc:
        
    End Function
    
    Private Sub cmdRun64BitCppClient_Click()
    
        If Not RunClient(App.Path & "\CppClient.exe") Then
            MsgBox "Unable to run client!", vbCritical
        End If
        
    End Sub
    
    Private Sub cmdRunScriptClient_Click()
    
        If Not RunClient(App.Path & "\script.hta") Then
            MsgBox "Unable to run client!", vbCritical
        End If
        
    End Sub
    
    Private Sub cmdRunVB6Client_Click()
        
        If Not RunClient(App.Path & "\ClientVB.exe") Then
            MsgBox "Unable to run client!", vbCritical
        End If
        
    End Sub
    
    Private Sub Form_Load()
        Me.Caption = Me.Caption & " 0x" & Hex(App.ThreadID)
    End Sub
    VB6 Client:

    Code:
    ' //
    ' // IPC using OBJRef moniker
    ' // Client app
    ' // by The trick 2020
    ' //
    
    Option Explicit
    
    Private Declare Function PathUnquoteSpaces Lib "shlwapi" _
                             Alias "PathUnquoteSpacesW" ( _
                             ByVal p As Long) As Long
    
    Private m_cServer   As Object
    
    Private Sub cmdKick_Click()
        m_cServer.Kick "Kick from 0x" & Hex$(App.ThreadID)
    End Sub
    
    Private Sub Form_Load()
        Dim pArg As Long
        
        Me.Caption = Me.Caption & " 0x" & Hex$(App.ThreadID)
        
        On Error GoTo error_handler
        
        pArg = StrPtr(Command$)
        PathUnquoteSpaces pArg
        Set m_cServer = GetObject(SysAllocString(pArg))
        
        cmdKick.Enabled = Not m_cServer Is Nothing
        
    error_handler:
        
    End Sub
    
    Private Sub Form_Unload(Cancel As Integer)
    
        If Not m_cServer Is Nothing Then
            m_cServer.ClientDisconnect
            Set m_cServer = Nothing
        End If
        
    End Sub
    C++ client:
    Code:
    //
    // IPC using OBJRef moniker
    // Client app
    // by The trick 2020
    //
    
    #include <Windows.h>
    #include <tchar.h>
    #include <Shlwapi.h>
    #include <atlbase.h>
    
    INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) {
    	switch (uMsg) {
    	case WM_INITDIALOG:
    		SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
    		break;
    	case WM_CLOSE:
    		EndDialog(hwndDlg, 1);
    		return TRUE;
    	case WM_COMMAND:
    		switch (LOWORD(wParam)) {
    		case 1:
    			CComDispatchDriver pHost((IDispatch*)GetWindowLongPtr(hwndDlg, DWLP_USER));
    			CComBSTR strTIDhex(80);
    			_ui64tot(GetCurrentThreadId(), strTIDhex.m_str, 16);
    			CComBSTR sMsg(L"Kick from 64-bit 0x");
    			sMsg.Append(strTIDhex);
    			pHost.Invoke1(L"Kick", &CComVariant(sMsg));
    		}
    		break;
    	}
    
    	return FALSE;
    }
    
    int APIENTRY _tWinMain(HINSTANCE hInstance, 
    					   HINSTANCE hPrevInstance,
    					   LPTSTR lpCmdLine,
    					   int nCmdShow) {
    	HRESULT hr = S_OK;
    	ULONG lEaten;
    	CComPtr<IMoniker> pMoniker;
    	CComPtr<IBindCtx> pCtx;
    	CComDispatchDriver pHost;
    
    	PathUnquoteSpaces(lpCmdLine);
    
    	CoInitialize(NULL);
    
    	CreateBindCtx(0, &pCtx);
    
    	if (FAILED(hr = MkParseDisplayName(pCtx, lpCmdLine, &lEaten, &pMoniker))) {
    		MessageBox(NULL, _T("Unable to connect to server"), NULL, MB_ICONERROR);
    		return hr;
    	}
    	
    	if (FAILED(hr = pMoniker->BindToObject(pCtx, NULL, __uuidof(IDispatch), (void**)&pHost))) {
    		MessageBox(NULL, _T("Unable to bind to server"), NULL, MB_ICONERROR);
    		return hr;
    	}
    
    	struct {
    		DLGTEMPLATE hTemp;
    		SHORT hMenu;
    		SHORT hClass;
    		WCHAR pszTitle[24];
    		SHORT wFontSize;
    		WCHAR pszFontname[14];
    		DLGITEMTEMPLATE hButton;     
    		SHORT wClass[2];
    		WCHAR pszCaption[6];
    		SHORT wDate;
    	} hTemplate = {{WS_CAPTION | WS_SYSMENU | DS_SETFONT | DS_CENTER, 0, 1, 0, 0, 200, 100}, 
    				   0, 0, L"IPC client by The trick", 8, L"MS Sans Serif",
    				   {BS_PUSHBUTTON | WS_VISIBLE, 0, 75, 35, 50, 30, 1}, 0xffff, 0x0080, L"Kick!", 0};
    
    	DialogBoxIndirectParam(NULL, (DLGTEMPLATE*)&hTemplate, NULL, DialogProc, (LPARAM)pHost.p); 
    
    	pHost.Invoke0(L"ClientDisconnect");
    
    	return hr;
    }
    HTA Client:
    Code:
    <HTML>
    <HEAD>
    <HTA:APPLICATION
        ID="OBJRefTest"
        APPLICATIONNAME="OBJRef Test"
        BORDER="Dialog"
        CAPTION="Yes"
        SCROLL="NO"
        SHOWINTASKBAR="yes"
        SINGLEINSTANCE="yes"
        SYSMENU="Yes"
        WINDOWSTATE="normal">
        SINGLEINSTANCE=”yes”>
    </HEAD>
    
        <SCRIPT language="vbscript">
        Dim pHost
        
        sub OnUnload()
            if not pHost is nothing then
                pHost.ClientDisconnect
            end if
        end sub
    
        sub OnLoad()
            
            window.resizeTo 300,150
    
            Set pHost = Nothing
    
            With New RegExp
                .Global = True
                .Pattern = """([^""]+)"""
                Set c = .Execute(OBJRefTest.CommandLine)
            End With
            
            if c.Count = 2 then
                Set pHost = GetObject(c(1).SubMatches(0))
            end if
    
        end sub
    
        sub Kick()
            if not pHost is nothing then
                pHost.Kick "Kick from script!"
            end if
        end sub
    
       </SCRIPT>
    
    <BODY onLoad="OnLoad()">
    <BODY onbeforeunload="OnUnload()">
    <FORM name=myform><button onclick='Kick()'>Kick!</button></FORM>
    </BODY>
    </HTML>
    Attached Files Attached Files

  14. #14
    Fanatic Member
    Join Date
    Jun 2016
    Location
    España
    Posts
    630

    Re: form shared in two different executables (projects)

    very good example Trick
    It could be done without TLB

    Greetings

  15. #15
    PowerPoster
    Join Date
    Jan 2020
    Posts
    5,538

    Re: form shared in two different executables (projects)

    Very good,thank you very much

Tags for this Thread

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width