1. kevin kevin rowe
  2. PowerBuilder
  3. Thursday, 16 June 2022 10:17 AM UTC

I'm trying to call a simple dll function to measure a piece of text, to see if it will fit in a confined space without being clipped.

I have defined an external DLL in C# and have linked it into the PB source using external function.

 

In my first attempt, I used float arguments as the C# utility routine uses float, and linked the function using the PB datatype Real. This caused a run time crash with no discernable codes except the usual 'well, that didn't work!' type message from PB.

I altered the DLL code to use int instead and tried to relink it using the Long parameter type but it will not compile now.

I have tried int, long and longlong.

Error message 

  ---------- Compiler: Errors (10:40:55)
cobs2.pbl(w_appmain).w_appmain.of_addbutton.46: Error C0116: Reference argument type does not match function definition: getwordwidth
---------- Finished Errors (10:40:55)

 

function definition in PB

 

FUNCTION long GetWordWidth(string asString, string asFont, long aiPointsize, ref long aiheight ) LIBRARY "flutils.dll"

 

To be certain about the conversion, I imported the DLL using the import function.

This is what was generated.

public function long of_getwordwidth(string as_asstring,string as_asfont,long al_aipointsize,ref long al_aiheight);
//*-----------------------------------------------------------------*/
//* .NET function : GetWordWidth
//* Argument:
//* String as_asstring
//* String as_asfont
//* Long al_aipointsize
//* Long al_aiheight
//* Return : Long
//*-----------------------------------------------------------------*/
Return This.getwordwidth(as_asstring,as_asfont,al_aipointsize,ref al_aiheight)
end function

 

Here is the C# source code. I have independently tested this with a console test harness and I know it works.

 

public int GetWordWidth(string asString, string asFont, int aiPointsize, ref int aiheight)
{
TextBox tx = new TextBox();
Graphics g = tx.CreateGraphics();
Font stringFont = new Font(asFont, aiPointsize);
SizeF wordbounds;

wordbounds = g.MeasureString(asString, stringFont);

aiheight = Convert.ToInt32(wordbounds.Height);

return Convert.ToInt32(wordbounds.Width);
}

What am I doing wrong?

 

 

 

 

Accepted Answer
John Fauss Accepted Answer Pending Moderation
  1. Thursday, 16 June 2022 14:07 PM UTC
  2. PowerBuilder
  3. # Permalink

Hi, Kevin - 

Have you considered utilizing the Windows API function GetTextExtentPoint32W to accomplish this? It's possible to call this API from PowerBuilder without using an intermediary DLL.

Here are links to a couple of sample applications that call this API:

Roland Smith's DataWindow Grid Service free code example:

   https://www.topwizprogramming.com/freecode_dwgridxp.html

An app I've made available in CodeXchange:

   https://community.appeon.com/index.php/codeexchange/powerbuilder/280-string-break-adds-line-breaks-to-strings-by-analyzing-content#429

The "trick" to getting this WinAPI function to work is having a static text control (it can be hidden or moved outside of a window's visible workspace) that uses the font typeface, point size, and attributes (bold/normal, italics, underlined, etc.) you want to use to measure. Of course, all graphical WinAPI functions operate with pixels, not PowerBuilderUnits (PBU's), you just have to keep that in mind and use the PowerScript functions UnitsToPixels and PixelsToUnits appropriately when needed.

In my CodeXchange app, it can optionally use other WinAPI functions that will insert an ellipsis (...) if the text being measured does not fit the available space.

Regards, John

Comment
  1. kevin kevin rowe
  2. Friday, 17 June 2022 13:37 PM UTC
Thanks John, and special thanks to Roland. I've credited him in the code I based on his. You guys dug me out of another hole.
  1. Helpful
There are no comments made yet.
Roland Smith Accepted Answer Pending Moderation
  1. Thursday, 16 June 2022 13:16 PM UTC
  2. PowerBuilder
  3. # 1

The Windows API function GetTextExtentPoint32 can be used to determine the width of text in pixels.

I have a code example that among other things uses this function to provide column autowidth on a grid datawindow.

https://www.topwizprogramming.com/freecode_dwgridxp.html

Take a look at of_ResizeWidth in n_svc_dw_gridstyle.

 

Comment
There are no comments made yet.
Chris Pollach @Appeon Accepted Answer Pending Moderation
  1. Thursday, 16 June 2022 12:19 PM UTC
  2. PowerBuilder
  3. # 2

Hi Kevin;

  If your .net assembly is in C#, then I would recommend trying...

https://docs.appeon.com/pb2019r2/whats_new/ch01s03.html

Regards ... Chris 

Comment
  1. René Ullrich
  2. Thursday, 16 June 2022 12:38 PM UTC
additional explanation:

A .net assembly it not a "real" DLL (dynamic link libraries). You can't access it using external function declaration.
  1. Helpful 1
There are no comments made yet.
kevin kevin rowe Accepted Answer Pending Moderation
  1. Thursday, 16 June 2022 10:54 AM UTC
  2. PowerBuilder
  3. # 3

D'Oh!

 

Well having fixed the issue with the parameters, I've got back to the issue of it simply crashing without any kind of feedback.  

 

I will try the imported function and see if that gives me any feedback

 

Comment
There are no comments made yet.
René Ullrich Accepted Answer Pending Moderation
  1. Thursday, 16 June 2022 10:22 AM UTC
  2. PowerBuilder
  3. # 4

Your error is in w_appmain.of_addbutton. Look there if are all arguments of correct type.

BTW: Why do you call getwordwidth in of_addbutton and not of_getwordwidth?

Comment
There are no comments made yet.
  • Page :
  • 1


There are no replies made for this question yet.
However, you are not allowed to reply to this question.