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:confused:
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
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.
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.
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.
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.
Re: form shared in two different executables (projects)
Quote:
imo this is a gotcha waiting to happen.
... and in mine, too!
1 Attachment(s)
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):
Attachment 167517
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
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)…
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.
Re: form shared in two different executables (projects)
To identify a COM object instance the COM uses monikers. You can use for example an ObjRef moniker to bind two executables.
Re: form shared in two different executables (projects)
Quote:
Originally Posted by
The trick
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
1 Attachment(s)
Re: form shared in two different executables (projects)
Quote:
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>
Re: form shared in two different executables (projects)
very good example Trick
It could be done without TLB
Greetings
Re: form shared in two different executables (projects)
Very good,thank you very much