|
I am trying to create MFC-based dll that will present SDI Doc/View interface
to the user.
[my question is at the end of this rather lengthy post]
This dll will be called from Win32 application that is not MFC based (also,
this app is
written in C, not in C++).
I created MFC-based dll project (called MFCDLL) using the Wizard.
In this project I created following classes:
CPrintingDoc (derived from CDocument)
CPrintingView (derived from CView)
CMainFrame (derived from CFrameWnd)
I created an exported function in this dll:
extern "C" __declspec(dllexport) int SomeFunction(int n)
{
AFX_MANAGE_STATE(AfxGetStaticModuleState( ));
theApp.Initialize();
return ++n;
}
My intent is that Win32 application calls SomeFunction(), and SomeFunction
initializes Doc/View environment. Related piece of code looks like this:
BOOL CMFCDLLApp::Initialize()
{
AfxEnableControlContainer();
// Register the application's document templates. Document templates
// serve as the connection between documents, frame windows and views.
CSingleDocTemplate* pDocTemplate;
pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CPrintingDoc),
RUNTIME_CLASS(CMainFrame), // main SDI frame window
RUNTIME_CLASS(CPrintingView));
AddDocTemplate(pDocTemplate);
// Parse command line for standard shell commands, DDE, file open
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// Dispatch commands specified on the command line
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// The one and only window has been initialized, so show and update it.
m_pMainWnd->ShowWindow(SW_SHOW);
m_pMainWnd->UpdateWindow();
return TRUE;
}
Essentially I replicated by hand the code that wizard generates for the
MFC-based .exe application
I also created String Table resource in this dll and added the following
string to it:
IDR_MAINFRAME TEST\n\nTEST\n\n\nTEST.Document\nTEST Document
When I start Win32 application and call SomeFunction() I get the dialog box
with message:
"Failed to create empty document",
and the view is not created.
Stepping through the code I found that the document is actually successfully
created
in function
CDocument* CSingleDocTemplate::OpenDocumentFile(LPCTSTR lpszPathName,
BOOL bMakeVisible)
This function is in file DOCSINGL.CPP (MFC source code). Document is created
in line 112:
[line 112] pDocument = CreateNewDocument();
The problem lies further in the same function, when in line 132 it attempts
to create the
frame:
[line 132] pFrame = CreateNewFrame(pDocument, NULL);
This function call returns NULL, the frame is not created, and this is why I am receiving this error message.
So my understanding at this point is that I maybe have to create this frame
window
myself somewhere in CMFCDLLApp::Initialize() before
if (!ProcessShellCommand(cmdInfo))
line (the failed attempt of frame creation is deep inside
ProcessShellCommand())
Is that right ? How would I do this ?
Or maybe I am going in the completely wrong direction - in that case please
suggest what
I need to do differently
|
|
|
|
|
Hi,
I don't have any experience with dlls. I have created a resource only dll and I want to call the resources from a different project, a SDI application. How do I so that? Please reply
|
|
|
|
|
first you need to load the resource dll using loadlibrary and get its instance handle.
Now this instance handle should be supplied to ::LoadIcon
::LoadString etc where ever it is necessary,
The resource.h file of the resource only dll should be #inclueded in ur sdi application, be carefull it may clash with ur sdi resource.h file too.
there are other apis releated to resoruce handling you can refer MSDN for that.
My God is more powerfull Than Your God. (the line that divides the world)
|
|
|
|
|
I guess this is not actually a C++ question but can someone shed some light on the meaning of these paths ( I am not even sure what they are called ).
1) . ( does this mean current dir )
2) ..\\
3) ..\\..\\
4) \somedir\debug\someexe.exe
I sometimes need these when doing a postcompile copy of a dll to a working folder. I don't like to use paths like c:\program\plugindir\ for example. I would search the net myself I just don't know what to search for.
Thanks
|
|
|
|
|
smesser wrote:
1) . ( does this mean current dir )
2) ..\\
3) ..\\..\\
4) \somedir\debug\someexe.exe
First off - notice that in 1-3, you used \\ and in 4 you used \.
Using '//' is a C/C++ language feature (double escape sequence) and not the way you would navigate directories in an OS. Using '\\' is a way to let the OS know that you are referring to a network resource - but only after the drive letter. I have never used - or seen used - '\\' to define subdirectories.
1 - current directory - current directory is OS dependent. Some OS' determine a system-wide current directory according to the last directory accessed (ie MS-DOS). Current directory may also be relative to the logged in user's last disk access.
2 - ..\\ refers to the parent directory of the current directory (see #1)
3 - ..\\..\\ refers to the parent directory of the parent directory of the current directory (see #1)
4 - Is an absolute path from the root drive of the current directory. It could also be relative to the home directory of the currently logged account/website/whatever
The relative paths could be different depending upon what permissions you have when you access the resource in question. If your server has C:, D: & E: hard drives and you have a web client whose login directory is on E:\users\joblo and there was a file E:\users\joblo\index.html then you (as a user with root acces) would access it as E:\users\joblo\index.html but he would access it as \index.html
If you used an app to access that file path and you entered \index.html, you might end up with a totally different file (most likely a file named index.html that resided on your machine's bootable hard drive).
|
|
|
|
|
Terry,
Thanks, very useful information for me.
Opps I did confuse the issue a little with the double slashes but thanks for seeing through to my real question.
Steve
|
|
|
|
|
Hi,
Is it at all possible to create several executables in the same project? I'm using Visual C++ .NET 2002.
I would like to be able to quickly create small test programs using the classes I develop for my main program in the project. So I would just like to be able to add a small testfile containing just a simple console prog and do some simple tests.
Please forgive me if this is a stupid question, but I have only recently started using VS and I have searched the documentation without finding the answer.
thanks
Luddet
|
|
|
|
|
In your solution
File - Add Project - New Project / Existing Project.
(Solution can contain many projects, the term has changed)
Sonork 100.41263:Anthony_Yio
|
|
|
|
|
Thanks, but I know that one solution can contain many projects. That's not what I'm after.
I need to know if it's possible to have several files with a main() or WinMain() in each, and have each one of them generate an executable. And I want to have them in the same project.
I know I can setup another project and "Add existing..." and selecting files from another project. But I don't like to litter my workspace with too many projects with the accompanying directories in my solution directory.
|
|
|
|
|
I think you are talking about MAKE file. You can configure the MAKE file to do the thing that you want. However, i am not familiar with it.
Another option if you do not want to edit your MAKE is you configure your IDE to do batch build.
Hope this helps.
Sonork 100.41263:Anthony_Yio
|
|
|
|
|
Hmmm... that sounds kind of involved too...
But I'll have a look at it anyway.
Thanks
/luddet
|
|
|
|
|
luddet wrote:
I need to know if it's possible to have several files with a main() or WinMain() in each, and have each one of them generate an executable. And I want to have them in the same project.
No. A project produces only one executable unless you mess with make files or custom builds to rig it to make more than one executable.
Use multiple projects and do batch builds. I do this all the time. For vc6 I have an addin that I run msvc from the command line and it will build all projects in the workspace.
John
|
|
|
|
|
well, batch builds is a piece of cake in .net, just SHIFT+CTRL+B.
I guess I'll just have to setup an extra test project for each regular project then
thanks for your help guys
/luddet
|
|
|
|
|
Hi,
I want to access and show a few html files and jpg files. I am thinking about making a resource only dll containing the html and jpg files. But I have never made one and I have few questions, Please reply.
1. My SDI project and Resource Only DLL should be two separate project, or I can include a resource only dll in my SDI application?
2. How do I access the resources in the dll from my application?
3. If SDI application and the dll are 2 separate project how are they loaded together, so that if I port my exe to a different machine it would work?
4. .jpg files are what kind of resources? because I just see ico and bitmap resources in the resource import dialog.
Please advise soon
Thanks
|
|
|
|
|
1. YOu need to have 2 seperate workspace one for your sdi
application and other for ur resource only dll.
2. The projects will be definitely be 2 but you can insert the resource only project into ur sdi project workspace so that you can work on both simultaneously.
3. You need to supply both the modules when installing in other machines and also other dlls that ur modules are depending upon ( you can get the list by using depends.exe supplied with visual studio.
4..jpg will be inserted as custom resource loading and using custom resource is a different topic, (that i dont know much about)
hope i answered ur quries.
My God is more powerfull Than Your God. (the line that divides the world)
|
|
|
|
|
Hi everyone,
I have a small set of classes that use MFC's CDatabase class to communicate with SQL server. I need to convert my classes to an ATL control because I need to use it in a C# SOAP Web service.
The CDatabase performance is not very good, in my opinion. Anyways, I was thinking of taking this opportunity to optimize my code as well. So, I was wondering what would be the best database library to use in your opinion. I am developing under VC++ 6.0. No scope for any .NET stuff with this one.
Looking forward to hearing from you fine folks.
Sincerely,
Pankaj
Without struggle, there is no progress
|
|
|
|
|
|
what is the command for getting a pointer to the document class from a dialog class. Sorry if this is a basic question, but I don't seem to know how to get variables from the doc class from my document class
Q-Bus
|
|
|
|
|
Add a member variable for your dialog class to store the pointer to the document.
After instantiating but before calling your dialog, assign the pointer for your document class to this new member variable.
|
|
|
|
|
Create the dialog box in Document class.
if var1 and var2 are 2 variables of document class to be used by dialog class.
if var3 and var4 are variables of dialog box class.
CMyDoc::MyFunc()
{
CMyDialog Mydlg;
Mydlg.var3 = var1;
Mydlg.var4 = var2;
if(Mydlg.DoModal()= IDOK)
{
var1 = Mydlg.var3;
var2 = Mydlg.var4;
}
}
never say die
|
|
|
|
|
I've a table in an Access database with an AutoNumber field. When I add a row to the table through a CRecordset object, I want to know the value of the AutoNumber field. I've read various articles on how this is done, but none of them work. The code basically looks like:
CMyRecordset set;
CDBVariant bookmark;
set.Open(AFX_DB_USE_DEFAULT_TYPE, NULL, CRecordset::useBookmarks);
set.AddNew();
set.field1 = 123;
set.field2 = 456;
...
set.GetBookmark(bookmark);
not been updated
set.Update();
the current one
set.Requery();
set.SetBookmark(bookmark); I successfully use bookmarks in other areas of the program when editing rows. I populate a listbox with each record in a recordset and assign the AutoNumber field using SetItemData() . When an item in the listbox is selected and the Edit button is clicked, I have the correct bookmark and can then use SetBookmark() and Edit() successfully. Using this scenario, if a newly added listbox item does not have a correct bookmark associated with it, SetBookmark() cannot be used prior to Edit() or Delete() calls. In other words, I have no way to navigate to the desired record.
Any ideas for this long-winded request?
Thanks,
DC
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
In theory - you need to obtain an exclusive lock to your datasource (I don't know how to do this because depending on ODBC drivers/ADO vrs DAO/etc. it changes). Then do the insert. Then query for MAX on the ID column. This will give you access to the newly inserted record. Then unlock it.
|
|
|
|
|
Terry O`Nolley wrote:
In theory - you need to obtain an exclusive lock to your datasource...
I'll try this, but I'm not following your logic. What would an exclusive lock on a single-user database have to with being able to query an AutoNumber field of a newly-added record?
I guess my main concern is that the dozen or so examples I looked at on MSDN and the Internet all showed basically the same approach: after an Update() , get the bookmark, call Requery() , set the bookmark, get the AutoNumber field value. The problem seems to be that after the call to Update() , the recordset is positioned back at the first record.
Five birds are sitting on a fence.
Three of them decide to fly off.
How many are left?
|
|
|
|
|
DavidCrow wrote:
I'll try this, but I'm not following your logic. What would an exclusive lock on a single-user database have to with being able to query an AutoNumber field of a newly-added record?
I didn't realize it was a single-user DB.
If it is a single user DB then you don't need the lock. Just do the insert and query for MAX ID.
If your ID field is an auto-number, then the MAX will be the newly inserted record.
Using LOCK prevents other records from being inserted while you do your insert.
|
|
|
|
|
after update you are requerying and setting the bookmark. this is wrong.
you can get bookmark of a current record after you update. and bookmarks are valid only for navigating in the current recordsets. once you close and reopen or requery then the bookmarks get vanished. you should call recordset.canbookmark() to check whether it is possible to bookmark or not. use CDatabase::GetBookmarkPersistence.
always use exception handling in database programming to get the actual cause of erro.
never say die
|
|
|
|