How to draw a chinese (Unicode) text on a window?

Hi experts,

I have a VB form that calls a "C" function (implemented in a DLL) to draw the text on the VB form. The VB form sends the window hDC, text position, font name, font size and the chinese text

The "C" code appears to draw something but the content is not correct. It looks like a wrong chinese is getting displayed.

I am providing the sample code.

VB project needs a text box and form_load needs to initialize a font. After entering the text in the text box, click enter so that it calls the "C" function to draw the text

Could you please help?

C code
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
HFONT m_hFont;
LOGFONT m_LogFont;
_TCHAR m_szSection[256];
_TCHAR m_szEntry[256];
void DefaultFontInit();
HFONT CreateFontLocal();
long lWindowDC,
_TCHAR *lpszFontName,
long lFontSize,
_TCHAR *lpszMultiByteText,
long X,
long Y)
long nFontHeight = 0;
long nLen = 0;
long nStatus = 0;
_tcscpy(m_szSection, _T("Settings"));
_tcscpy(m_szEntry, _T("Font"));
nFontHeight = - MulDiv (lFontSize, GetDeviceCaps (GetDC (0), LOGPIXELSY), 72);
DefaultFontInit(lpszFontName, nFontHeight);
nLen = _tcslen(lpszMultiByteText);
nStatus = TextOut(lWindowDC, X, Y, &lpszMultiByteText, nLen);
return (0);
void DefaultFontInit(_TCHAR *lpszFontName, long nFontHeight)
HFONT hFont;
// define the logical parameters for the default font
//m_LogFont.lfHeight = -11; // size 8
m_LogFont.lfHeight = nFontHeight;
m_LogFont.lfWidth = 0;
m_LogFont.lfEscapement = 0;
m_LogFont.lfOrientation = 0;
m_LogFont.lfWeight = FW_NORMAL;
m_LogFont.lfItalic = 0;
m_LogFont.lfUnderline = 0;
m_LogFont.lfStrikeOut = 0;
m_LogFont.lfCharSet = 0;
m_LogFont.lfOutPrecision = OUT_STRING_PRECIS;
m_LogFont.lfClipPrecision = CLIP_STROKE_PRECIS;
m_LogFont.lfQuality = DEFAULT_QUALITY;
m_LogFont.lfPitchAndFamily = FF_SWISS | VARIABLE_PITCH;
//_tcscpy(m_LogFont.lfFaceName, _T("Lucida Sans Unicode"));
_tcscpy(m_LogFont.lfFaceName, lpszFontName);
// create the associated font 
hFont = CreateFontLocal();
HFONT CreateFontLocal()
HFONT hFont = CreateFontIndirect(&m_LogFont);
if (hFont == NULL)
// GetLastError(); can be used to understand why the font was not created
MessageBox(0, _T("Impossible to create font\n"), _T("My Sample"), 0);
// don't forget to delete the current font
if (m_hFont != NULL)
// store the font (event if the creation has failed)
m_hFont = hFont;
return hFont;
VB code
Private Const FW_NORMAL = 400
Private Const DEFAULT_CHARSET = 1
Private Const OUT_DEFAULT_PRECIS = 0
Private Const DEFAULT_QUALITY = 0
Private Const VARIABLE_PITCH = 2
Private Const FF_SWISS = 32 ' Variable stroke width, sans-serifed.
Private Const GCS_RESULTSTR = &H800
Private Const GCS_RESULTREADSTR = &H200
Private Const GCS_COMPSTR = &H8
Private Const GCS_COMPREADSTR = &H1
Private Declare Function GetDC Lib "user32" (ByVal hwnd As Long) As Long
Private Declare Function MyProjectDrawText Lib "CodeProjectSample.dll" ( _
ByVal lWindowDc As Long, _
ByVal szFontName As String, _
ByVal szFontSize As Long, _
ByVal lstrText As String, _
ByVal x As Long, _
ByVal y As Long) _
As Long
Private Declare Function GetDeviceCaps Lib "gdi32" (ByVal hdc As Long, ByVal nIndex As Long) As Long
Private Declare Function ImmGetContext Lib "imm32.dll" (ByVal hwnd As Long) As Long
Private Declare Function ImmGetOpenStatus Lib "imm32.dll" (ByVal himc As Long) As Long
Private Declare Function ImmGetCompositionString Lib "imm32.dll" Alias "ImmGetCompositionStringA" (ByVal himc As Long, ByVal dw As Long, lpv As Any, ByVal dw2 As Long) As Long
Private Declare Function ImmReleaseContext Lib "imm32.dll" (ByVal hwnd As Long, ByVal himc As Long) As Long
Private Declare Function MulDiv Lib "kernel32" (ByVal nNumber As Long, ByVal nNumerator As Long, ByVal nDenominator As Long) As Long
Private Declare Function CreateFont Lib "gdi32" Alias "CreateFontA" (ByVal H As Long, ByVal W As Long, ByVal E As Long, ByVal O As Long, ByVal W As Long, ByVal I As Long, ByVal u As Long, ByVal S As Long, ByVal C As Long, ByVal OP As Long, ByVal CP As Long, ByVal Q As Long, ByVal PAF As Long, ByVal F As String) As Long
Private Declare Function TextOutW Lib "gdi32" (ByVal hdc As Long, ByVal x As Long, ByVal y As Long, ByVal lpString As Long, ByVal nCount As Long) As Long
Private Declare Function SelectObject Lib "gdi32" (ByVal hdc As Long, ByVal hObject As Long) As Long
Private lngMouseDownX As Long
Private lngMouseDownY As Long
Private strFontName As String
Private lngFontSize As Long
Private mstrMarkupText As String
Private Sub Form_Load()
lngFontSize = 20
strFontName = "ËÎÌå"
lngMouseDownX = 50
lngMouseDownY = 150
End Sub
Private Sub Text1_Change()
Dim hct As Long
Dim ll As Long
Dim len5 As Long
Dim str5() As Byte
Dim hwnd As Long
Dim GetCompositionResult As String
hwnd = Screen.ActiveForm.hwnd
GetCompositionResult = ""
hct = ImmGetContext(hwnd)
If hct = 0 Then
Exit Sub
End If
'Get the size of the result string
ll = ImmGetCompositionString(hct, GCS_RESULTSTR, vbNullString, 0)
If ll > 0 Then
'lstrText = ""
ReDim str5(0 To ll - 1)
len5 = ImmGetCompositionString(hct, GCS_RESULTSTR, str5(0), ll)
GetCompositionResult = StrConv(str5, vbUnicode)
End If
ImmReleaseContext hwnd, hct
Debug.Print "'" & GetCompositionResult & "'"
Call MyDrawText(Me.hdc, strFontName, lngFontSize, GetCompositionResult, lngMouseDownX, lngMouseDownY)
End Sub

Open in new window

Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Try this:
Change your Declare to:

Private Declare Function MyProjectDrawText Lib "CodeProjectSample.dll" ( _
ByVal lWindowDc As Long, _
ByVal szFontName As Long, _
ByVal szFontSize As Long, _
ByVal lstrText As Long, _
ByVal x As Long, _
ByVal y As Long) _
As Long

Use StrPtr:
Call MyDrawText(Me.hdc, StrPtr(strFontName), lngFontSize, StrPtr(GetCompositionResult), lngMouseDownX, lngMouseDownY)

Suggest you test first with a known Chinese string, then try with actual value of GetCompositionResult.

GetCompositionResult = "CHS: " & ChrW$(&H6B22) & ChrW$(&H8FCE)
nsangaAuthor Commented:

Thank you. I tried your suggestion. However, it didnt solve the problem.

Could you please let me know if you have some additional comments?

Thanks & regards,
I think you will need to change the C code to accept a BSTR pointer for the 2 strings that are being passed.
nsangaAuthor Commented:
OK, thank you.

I just changed my ".c" extension to ".cpp" and it started showing up the Chinese text properly.

I am still not sure what is going wrong with .c file


Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today

From novice to tech pro — start learning today.