Welcome!

PowerBuilder Authors: Chris Pollach, Yeshim Deniz, Jayaram Krishnaswamy, Kevin Benedict, Avi Rosenthal

Related Topics: PowerBuilder

PowerBuilder: Article

Implementing the Microsoft Rich Edit Control

Part 2

As we mentioned in Part 1 (PBDJ, Vol. 12, issue 7), we needed to implement spell checking in the rich edit fields in our application (see Figures 1 and 2).

To do that, we got a license for the Sentry Spelling Checker Engine from Wintertree Software (www.wintertree-software.com). The utility is easily implemented and works quite well on standard Rich Edit controls. However, the PowerBuilder Rich Edit control is an OEM version of an old third-party control that was popular before Microsoft introduced its Rich Edit control to the common controls. As a result, the messages and functions it supports are completely different from those that the Sentry utility is trying to use to interact with the control.

In Part 1 we created a custom visual user object based on the Microsoft Rich Edit control. In Part 2, we will write two custom DLLs to support the functionality of the rich edit control that we weren't able to implement directly through PowerBuilder. One is a PBNI extension and the other is a standard DLL.

enumfont PowerBuilder extension
Sybase made an enumfont PowerBuilder extension available as an example of implementing PBNI when PowerBuilder 9 was first released. However, as originally written, the extension wasn't fully suited to our purposes. This was primarily because it used the rather old EnumFontFamilies function in the Windows API and only allowed a choice between screen or printer fonts. The EnumFontFamilies function often returns a particular font family several times if there are multiple charsets for the same font family. Rather than trying to filter out the list returned by that function, we modified the extension to use the newer EnumFontFamiliesEx function. That method provides more control upfront over the selection of the font families that are returned, and we modified the extension so it only returns TrueType fonts that have an ANSI charset.

The changes to the original enumfont extension are primarily in two areas. In the call to the Windows API function (originally called EnumPrinterFonts or EnumScreenFonts, but now called EnumTrueTypeFonts), there is now an additional LOGFONT structure that's prepared and passed into the call to indicate the font characteristics the call should match.

EnumTrueTypeFonts
HDC hdc = GetDC(NULL);

UserData ud;
LOGFONT lf = { 0, 0, 0, 0, 0, 0, 0, 0, ANSI_CHARSET,
0, 0, 0, 0, "\0" };

ud.session = session;
ud.object = ci->pArgs->GetAt(0)->GetObject();

int ret = EnumFontFamiliesEx(hdc, &lf,
(FONTENUMPROC)&CFontEnumerator::EnumFontProc,
(LPARAM)&ud, 0 );
ReleaseDC(NULL, hdc);

ci->returnValue->SetLong((pblong)ret);

return PBX_OK;

The other major change is in the callback function (EnumFontProc) that the Windows API calls for each font name. Both the original version and the modified version contained a FontType argument that indicates (among other things) whether or not the font being passed in is a TrueType font. The difference is that we are now checking that argument for a TrueType font, and exiting the callback without proceeding further if it's not. In addition, the structure in which the font name is returned to the callback procedure has a slightly different format for the newer call.

EnumFontProc
UserData* ud = (UserData*)lparam;

if ( !( FontType & TRUETYPE_FONTTYPE ) )
{
   return 1 ;
}

pbclass clz = ud->session->GetClass(ud->object);
pbmethodID mid = ud->session->GetMethodID(clz, "onnewfont",
PBRT_EVENT, "IS");

PBCallInfo ci;
ud->session->InitCallInfo(clz, mid, &ci);

ci.pArgs->GetAt(0)->SetString(lpelfe->elfLogFont.lfFaceName);
ud->session->TriggerEvent(ud->object, mid, &ci);
pbint ret = ci.returnValue->GetInt();

ud->session->FreeCallInfo(&ci);

return 1 ;

richedit.dll
One of the principal reasons that a PBNI extension was used to get the list of fonts is because the Windows API function that returns that information requires a callback function to implement it, something that PowerBuilder doesn't directly support. The same issue came up in two other areas in our implementation:

  • Retrieving the RTF formatted text from the control using the EM_STREAMOUT Windows message.
  • Receiving notifications of selection changes in the rich edit control via the EN_SELCHANGE Windows message.
The richedit.dll was developed to provide callback support to the PowerBuilder user objects.

The richedit.dll contains four exported functions. Two of them are used to let the DLL know how to communicate back to the PowerBuilder object that's working with it. In both cases, the handle to the PowerBuilder user object is passed in as an argument and stored locally in the DLL.

SetControl
void __declspec(dllexport) __stdcall SetControl(
DWORD hControl
)
{
   iControl = (HWND)hControl ;
   return ;
}

SetUserObject
void __declspec(dllexport) __stdcall SetUserObject(
DWORD hUserObject
)
{
iUserObject = (HWND)hUserObject ;
return ;
}

More Stories By Bruce Armstrong

Bruce Armstrong is a development lead with Integrated Data Services (www.get-integrated.com). A charter member of TeamSybase, he has been using PowerBuilder since version 1.0.B. He was a contributing author to SYS-CON's PowerBuilder 4.0 Secrets of the Masters and the editor of SAMs' PowerBuilder 9: Advanced Client/Server Development.

More Stories By Demetrios Tsakiris

Demetrios Tsakiris is a senior programmer at Integrated Data Services. He has been working with PowerBuilder since version 5.0 and has a total of 5 1/2 years in the programming world. Demetrios is also an Oracle, Sybase, and Unix developer.

Comments (0)

Share your thoughts on this story.

Add your comment
You must be signed in to add a comment. Sign-in | Register

In accordance with our Comment Policy, we encourage comments that are on topic, relevant and to-the-point. We will remove comments that include profanity, personal attacks, racial slurs, threats of violence, or other inappropriate material that violates our Terms and Conditions, and will block users who make repeated violations. We ask all readers to expect diversity of opinion and to treat one another with dignity and respect.