|
Yes there is..
In fact, I pondered over this same problem a while back. The idea was that I was supposed to use a class which is completely declared inside a DLL. I only had the header files for reference.
So, here we go, first the actual class, declared with typedef. Do this in a seperate header file:
[code]
typedef class {
public:
// Some initialization functions ?
virtual HRESULT InitModule(void);
virtual HRESULT QuitModule(void);
// A member variable perhaps ?
int iMemberVariable;
} MyExportedClassType;
// Pointer-to-function returning address-of WindowPlugin class
typedef MyExportedClassType* (*GetClass)(void);
[/code]
What ? A pointer-to-function blablabla ? What's that ?
Simple: That is the key to this whole mess: a pointer to a function. Why is it declared there ? Because the same header file is used in the loading application. Just for the sake of simplicity.
Now, when we have the actual class, let's see the DLL exporting it:
[code]
// On global level, declare an instance of the class
MyExportedClassType MyClass;
// At the DllMain, initialize the class' members
int WINAPI DllMain(HINSTANCE hInstance, DWORD dwReason, LPVOID lpVoid)
{
.... Some code here
MyClass.iMemberVariable = 10;
.... More code here
return TRUE
}
// Add an exported function, which returns the address of our class
__declspec(dllexport) MyExportedClassType* ProvideAddressOfClass(void)
{
return &MyClass;
}
[/code]
Lastly, create a module definition file
[code]
LIBRARY
EXPORTS
ProvideAddressOfClass @1
[/code]
Ok, now the DLL is ready, go compile it. Next up, the loading application:
[code]
// We must include the typedef declaration
#include "myclasstypedef.h"
HDLL hDll;
// See here: let's create a pointer-to-function which returns a class' address.. Remember, we exported this type of function from the DLL !
GetClass MyClassProvider;
// A pointer to our class type
MyExportedClassType* lpImportedClass;
// Your main function
int main(void)
{
.... Some code ?
// Load module
hDll = LoadLibrary(ModuleName[iCount]);
// Resolve address of exported function
MyClassProvider = (GetClass)GetProcAddress(hDLL, "ProvideAddress");
// Get address of class within the DLL, using the exported function
lpImportedClass = MyClassProvider();
// Let's use it !
lpImportedClass->iMemberVariable = 1;
.... Some more code
// Remember to unload the library !
UnloadLibrary(hDll);
// End application
return 0;
}
[/code]
Seems difficult ? Well, it really isn't.. To sum it all up programmer-wise:
1. Create a class using typedef
2. Create a function which returns the address of your class
3. Export this function in the DLL with __declspec AND .def file
4. Create a typedef for 'pointer-to-function' of the address-provider function
5. Load the DLL in another application
6. Get the address of the exported function
7. Use the function to get the address of the class
8. Use the class
9. NULLify pointers, unload the DLL etc clean-up work
10. Quit and get some sleep
I have created an example of this, an application which actually creates it's main window in a seperate DLL, and adds event handlers to this window's procedure in another DLL. You can download the entire workspace (3 projects: WinDLL, InpDLL, WinLoader) from here.
Enjoy !
-Antti
|
|
|
|
|
[EDIT]I'm using VS6[/EDIT]
This is an obscure problem: I'm using an edit control labeled IDC_EDIT2 in a dialog-based app. To restrict the length of the content to 8, I use the following function that is called whenever the content changes:
void CFileCryptDlg::OnChangeEdit2()
{
char strPassword[10];
if(GetDlgItemText(IDC_EDIT2,strPassword,10)>8)
{
strPassword[8]='\0';
SetDlgItemText(IDC_EDIT2,strPassword);
}
}
It works fine, except for one small problem: till I type the 8th character, everything's as expected. But when the 9th character is typed, the cursor moves back to the first location in the edit box. How do I retain the cursor position?
Thanks,
Vikram.
The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offence.- Dijkstra
KI klike KDE kand kuse kit, kbut KI kmust kadmit, kstarting kall knames kwith K kis ksilly. KI khope kthey kwill kgive kup kthis kwhole kscheme ksoon kand kcome kup kwith kreal knames.
pI vThink aHungarian nNotation vIs iA aWonderful nThing cAnd pEveryone avShould vUse pIt aAll dThe nTime, adNo nMatter pWhat dThe nContext, adEven adWhen vSpeaking.
|
|
|
|
|
Why don't you just do SendMessage(wndOfYourEdit, EM_EXLIMITTEXT, 8, 0); ?
This will limit the edit control to accept max. 8 chars.
regards
modified 12-Sep-18 21:01pm.
|
|
|
|
|
I tried what David said below and it works.
On a purely academic note, how come neither
::SendMessage(((CEdit *)GetDlgItem(IDC_EDIT2))->m_hWnd, EM_EXLIMITTEXT, 8, 0);
nor
GetDlgItem(IDC_EDIT2)->SendMessage(EM_EXLIMITTEXT, 8, 0);
works when called from the dialog's InitInstance() function? They don't restrict the number of characters at all.
Cheers,
Vikram.
The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offence.- Dijkstra
KI klike KDE kand kuse kit, kbut KI kmust kadmit, kstarting kall knames kwith K kis ksilly. KI khope kthey kwill kgive kup kthis kwhole kscheme ksoon kand kcome kup kwith kreal knames.
pI vThink aHungarian nNotation vIs iA aWonderful nThing cAnd pEveryone avShould vUse pIt aAll dThe nTime, adNo nMatter pWhat dThe nContext, adEven adWhen vSpeaking.
|
|
|
|
|
Probably because a dialog does not have such a method. Are you talking about OnInitDialog() ? Either way, the EM_EXLIMITTEXT message is for rich edit controls.
|
|
|
|
|
Is your edit control already created in InitInstance()? I'd prefer OnInitDialog().
modified 12-Sep-18 21:01pm.
|
|
|
|
|
Why not just use SetLimitText(8) ?
|
|
|
|
|
Works!
Thanks a zillion !
Regards,
Vikram.
The use of COBOL cripples the mind; its teaching should, therefore, be regarded as a criminal offence.- Dijkstra
KI klike KDE kand kuse kit, kbut KI kmust kadmit, kstarting kall knames kwith K kis ksilly. KI khope kthey kwill kgive kup kthis kwhole kscheme ksoon kand kcome kup kwith kreal knames.
pI vThink aHungarian nNotation vIs iA aWonderful nThing cAnd pEveryone avShould vUse pIt aAll dThe nTime, adNo nMatter pWhat dThe nContext, adEven adWhen vSpeaking.
|
|
|
|
|
COleSafeArray::PutElement
Does this function append to the array ?
|
|
|
|
|
Nope. I can say this caregorically, since it's a wrapper around the SafeArrayPutElement function, and that doesn't.
Use the source, Luke
Steve S
|
|
|
|
|
This should be a simple question, but how do you create a CRichEditCtrl for version 2.0/3.0 using either Create or CreateEx?
Larry J. Siddens
Cornerstone Communications
TAME THE DOCUMENT MONSTER
www.unifier.biz
|
|
|
|
|
What specifically is not working for you? If the control's parent is a dialog, add a control variable to the dialog's .H file, and then in the dialog's OnInitDialog() method, add:
AfxInitRichEdit();<br />
richedit.Create(...);
|
|
|
|
|
Might be that they're wanting specifically to create a richedit with Word-style paragraph formatting (left, centre, right, align). The default MFC way means that an old style rich edit is created all the time. In some cases, the way I've done this is in OnInitDialog to get the old one's attributes, trash it and recreate the control in place, before calling the default OnInitDialog in case that maps a control.
There are two Windows class names, "RichEdit" which is v1.0 and RICHEDIT_CLASS which expands at compile time to produce the appropriate name for v2 or later.
Steve S
|
|
|
|
|
The AfxInitRichEdit() loads the RICHED32.DLL with is version 1.0. I want to load 2.0/3.0
Thanks
Larry J. Siddens
Cornerstone Communications
TAME THE DOCUMENT MONSTER
www.unifier.biz
|
|
|
|
|
My bad. When I saw richedit32, I just assumed v3.2, not 1.0. You have to go to richedit20 in order to get v3.0. Are we confused yet?
So, the moral to your story is that the CRichEditCtrl class does not support the Rich Edit v2.0 control. In order to use Rich Edit 2.0 in an MFC application, call LoadLibrary() to load the Riched20.dll and access its functionality through the Win32 API. Hmmm
|
|
|
|
|
So you use the LoadLibrary to load the riched20.dll and use the handle to set the fonts, formating, . . . Correct?
Can you place a small example. I have not called items from the library.
Thanks
Larry J. Siddens
Cornerstone Communications
TAME THE DOCUMENT MONSTER
www.unifier.biz
|
|
|
|
|
HMODULE hLibrary = LoadLibrary("riched20.dll");<br />
<br />
m_richedit = CreateWindowEx(0, RICHEDIT_CLASS, "", WS_CHILD | WS_VISIBLE | ES_MULTILINE, 5, 50, 100, 100, GetSafeHwnd(), NULL, NULL, NULL);<br />
<br />
::SendMessage(m_richedit, WM_PASTE, 0, 0);
|
|
|
|
|
You are loading the library to check if the riched20.dll is there correct? Now I have one more question. Have you been able to print that area correctly? If so, how? I'm trying to do that. The problem is that we don't know what the output device will be at the time of creation. Interesting twist huh?
Thanks again.
Larry J. Siddens
Cornerstone Communications
TAME THE DOCUMENT MONSTER
www.unifier.biz
|
|
|
|
|
Use EM_SETTARGETDEVICE to set the target device. Then use EM_FORMATRANGE and EM_DISPLAYBAND to display the control's contents. See the MSDN article Q129860.
|
|
|
|
|
Thats the caveat Dave, we don't know what the device is when the use uses it! What I'm currently doing is pulling each line out, scanning for font differences and using the TextOut to draw the text. Problem is that the font that shows up on the screen (fitting inside of a box) is either bigger or smaller than what was on the screen.
Kind of an interesting puzzle huh?
Larry J. Siddens
Cornerstone Communications
TAME THE DOCUMENT MONSTER
www.unifier.biz
|
|
|
|
|
Ok, I'm a tad confused at this point. Are you wanting to take text from a rich edit control and send it to a printer? It sounds like you need to use GetDeviceCaps() to make sure the target device is setup like the rich edit control.
|
|
|
|
|
Now I'm confussed? How do you do that? See if the target device is set up like a rich edit? Am I getting too deep here? I wish I did know what the target device was when the users used it, but that is the requirement.
Larry J. Siddens
Cornerstone Communications
TAME THE DOCUMENT MONSTER
www.unifier.biz
|
|
|
|
|
You have a rich edit control on a dialog or a form-based view. Yes? What are you wanting to do with the text in the control? As I understood your earlier post, you want to take the text in the control and send it to a printer. Yes?
|
|
|
|
|
I actually sits within an area on a scrollview. Kind of like a text box in word. Then when the time comes, draw the text to the printer or some other device.
Sorry for the confustion.
Larry J. Siddens
Cornerstone Communications
TAME THE DOCUMENT MONSTER
www.unifier.biz
|
|
|
|
|
I want to output the text in a rich edit control (there are many on the same page) with the same format and fonts usage as in the Rich Edit control. I thought I could use the FormatRange, but since I don't know what the target device is when it is being used, I'm not sure if that would work. So, I was getting one line at a time, then spending time to scan character by character checking the fonts used. When the font changs, then I would save off the font and the text. I continue until the whole line is scanned and getting the height of the text to the baseline. Setting the output to use the base line as the y parameter and outputting it to the device. This is so ineffecient it isn't funny. Am I correct in using FormatRange? OR, could I use FormatRange along with DisplayBand to output line by line. Again, inefficient than doing the whole thing, but it would be better than doing character by character.
Thanks Dave.
Larry
Larry J. Siddens
Cornerstone Communications
TAME THE DOCUMENT MONSTER
www.unifier.biz
|
|
|
|
|