How to get different language text by GetWindowText? - c++

How to get different language text by GetWindowText?
I have modfying a whiteboard project. When the user type in the whiteboard, the onchange function will called and will show the text in the whiteboard. However, when I type Japanese text (Non system default language) it shows "?" instead. The following is the code spinet for onchange.
void CHBEdit::OnChange()
{
static bool bChanged = true;
CDC *pDC = GetDC();
if (bChanged) {
CString str;
GetWindowText(str);
m_strText = str;
int iStartChar, iEndChar;
GetSel(iStartChar, iEndChar);
CRect rect;
GetWindowRect(&rect);
CFont *Oldfont = (CFont *)pDC->SelectObject(&m_Font);
CSize size = pDC->GetOutputTextExtent(str); //+ "a");
pDC->SelectObject(Oldfont);
SetWindowPos(NULL, 0, 0, size.cx, size.cy, SWP_NOMOVE);
bChanged = false;
SetWindowText(str);
SetSel(iStartChar, iEndChar);
}
else
bChanged = true;
ReleaseDC(pDC);
}
I am really new in C++. I did research and had tried GetwindowTextW with UTF8 unicode, but it still showing "?". Maybe the logic wrong.
I would appreciate it if anyone could give me the solution to show different language text in the whiteboard. Thank you.

GetWindowTextW is the right way. Windows uses UTF16 Unicode standard, with wchar_t wide string. UTF8 standard is commonly used with Linux and internet. You may need UTF16/UTF8 conversion only when exporting/importing data to other systems.
If you create a new MFC project it will be setup in Unicode and MFC functions will default to Unicode. Example:
//UNICODE project:
CString str;
GetWindowText(str);
MessageBox(str);
If project is Unicode, this will will work in Japanese and all other languages.
If you are working with a legacy MFC project which is stuck in in ANSI mode and you can't change it, use the following fix:
//ANSI project:
CStringW str;
GetWindowTextW(str);
MessageBoxW(str);

Related

MFC C++ CListBox get selected item

First let me say that I've been searching for a solution for couple of days now...
I'm trying to get selected item for ListBox. This is my code:
CListBox * pList1 = (CListBox *)GetDlgItem(IDC_LIST1);
CString ItemSelected;
// Get the name of the item selected in the Sample Tables list box
// and store it in the CString variable declared above
pList1->GetText(pList1->GetCurSel(), ItemSelected);
MessageBox(ItemSelected, "TEST", MB_OK);
Now when i try this i get an error message saying "The Parameter is incorect"
Your code looks OK except error handling. Also MessageBox parameters look incorrect. The first parameter should be of type HWND. I believe that this is the root cause of your problems. Use MFC standard AfxMessageBox instead:
CListBox * pList1 = (CListBox *)GetDlgItem(IDC_LIST1);
int nSel = pList1->GetCurSel();
if (nSel != LB_ERR)
{
CString ItemSelected;
pList1->GetText(nSel, ItemSelected);
AfxMessageBox(ItemSelected);
}
If the CListBox is in single selection mode, the CListBox::GetCurSel will return the selected index.
If the CListBox is in multi-selection mode, you should use CListBox::GetSelItems which will return a list of indices.
You cannot mix'n'match the functions.
And always check return codes (as others already wrote).
If You already have a data member MyList(of classCListBox) :
int nSel = MyList.GetCurSel();
CString ItemSelected;
if (nSel != LB_ERR)
{
MyList.GetText(nSel, ItemSelected);
}
CWnd class has a MessageBox function which does not need a HWND parameter. But yes, AfxMessageBox is a little bit more easier to use and can be called anywhere in the MFC code without having a CWnd-derived object. And a beside note: if call a WinAPI function inside MFC code (not needed here, but possible in other cases) it's good to prepend it with scope resolution operator in order to avoid any confusion, mistake and/or name conflict (e.g. ::MessageBox...).
One possible cause for "invalid parameter" error in OP code is that it uses an ANSI string literal ("TEST") in a UNICODE build configuration. This case, must use an UNICODE string literal (L"TEST") or a little bit better, use _T macro (_T("TEST")) that makes it possible to build in both ANSI and UNICODE configurations.

WxWidgets with Visual Studio and Unicode Sources

Following the UTF-8 everywhere manifesto, and mostly its part: how to do text on Windows, I've created this simple example with wxWidgets. I wanted wxWidgets to interpret string literals as UTF-8 strings, but it seems, that library gets me wrong.
single source file - main.cpp, encoded as UTF-8 without signature (in msvc terminology):
#include <wx/wx.h>
class Mainw: public wxFrame
{
public:
Mainw(wxWindow * parent, wxWindowID wxId, const wxString & label)
: wxFrame(parent, wxId, label)
{
wxBoxSizer * sizer = new wxBoxSizer(wxHORIZONTAL);
sizer->Add(new wxTextCtrl(this, wxID_ANY, wxT("Кириллица")), 1, wxEXPAND | wxALL, 5);
this->SetSizer(sizer);
}
};
class MyApp: public wxApp
{
public:
bool OnInit()
{
Mainw *f = new Mainw(NULL, wxID_ANY, wxT("Frame"));
f->Show();
return true;
}
};
IMPLEMENT_APP(MyApp)
Preprocessor Definitions:
UNICODE
_UNICODE
WIN32
__WXMSW__
_WINDOWS
_DEBUG
__WXDEBUG__
wxUSE_UNICODE=1
WXUSINGDLL=1
Linked with WxWidgets Library version 3.0.2
Headers - http://sourceforge.net/projects/wxwindows/files/3.0.2/wxWidgets-3.0.2_headers.7z/download
Binaries - http://sourceforge.net/projects/wxwindows/files/3.0.2/binaries/wxMSW-3.0.2_vc90_Dev.7z/download
Being run, this example produces window with text Кириллица, instead of Кириллица (there was something similar, but it changed to this, when I tried to select it to copy here). It means, that wxWidgets fails to interpret my string literal as UTF-8, but interprets it as something else - maybe as text in system encoding which is windows-1251.
Is there any way to change this behavior of library to match utf-8 everywhere manifesto?
Conclusion:
I gave up. I managed to build library with msvc and flag wxUSE_UNICODE_UTF8 but it would not help without some complex changes in library configuration headers. It seems, that this option is POSIX only
Is there any way to change this behavior of library to match utf-8 everywhere manifesto?
No, not under Windows because Windows doesn't support UTF-8 locales (in principle, they could be emulated by the CRT, but AFAIK no compiler does it) and wxString(const char*) ctor interprets the string in the current locale encoding by default.
There are two simple solutions however:
Use wxString::FromUTF8() explicitly.
Use wxString(const wchar_t*) ctor with L"..." wide char argument.
Just for completeness, you also might force the library into accepting UTF-8 narrow text by rebuilding it with wxUSE_UTF8_LOCALE_ONLY=1, but I'm far from sure if this is going to work because the CRT locale will still be different and so using non-ASCII characters with any CRT functions will most likely not work as expected, so I definitely do not recommend doing this unless you're just curious to see what happens.

How can I use MBCS to support a language without codepage?

An MFC application need an edit ctrl in dialog for edit Tamil language.
But I found the Tamil language does not have code page in Windows (Yes, there isn't Tamil system locale), and the Unicode option is not in my situation.
Saw someone idea, Embedding HWND into external process using SetParent
I wanna to create another application built with UNICODE option, embed its window to the dialog, but failed.
Check the MSDN, SetParent need the parent and child window in one application.
So, how can I implement it?
#MSalters
I solved it by override virtual BOOL CWinThread::PumpMessage(), force the message loop use W version API.
BOOL CtamildlgApp::PumpMessage()
{
_AFX_THREAD_STATE *pState = AfxGetThreadState();
if ( !::GetMessageW( &( pState->m_msgCur ), NULL, NULL, NULL ) )
{
// Note: prevents calling message loop things in 'ExitInstance'
// will never be decremented
return FALSE;
}
// process this message
if ( pState->m_msgCur.message != WM_KICKIDLE )
{
::TranslateMessage( &( pState->m_msgCur ) );
::DispatchMessageW( &( pState->m_msgCur ) );
}
return TRUE;
}
Then CreateWindowExW(... MSFTEDIT_CLASS ...)
Tamil is indeed harder than usual. But still there's one thing obvious: use Unicode, not MBCS. Internally, all Windows functions are Unicode. The MBCS wrappers use the current code page to translate from multi-byte encodings to UTF-16. E.g. when you call MessageBoxA("Some String"), the current code page is used to translate that into a call of MessageBoxW(L"Some String").
Now, this directly means that you cannot call MessageBoxA("Narrow Tamil String") since there's no code page to convert that into the appropriate wide string. You MUST call the Unicode function MessageBoxW("Narrow Tamil String") directly.
MFC cannot magically make this problem go away. It may provide a nicer syntax for some calls, wrapping Win32 idioms in classes, constructors and destuctors. But it can't create missing code pages out of thin air.

Is there a Mac OSX version of windows GetFontData function?

We have an application that allows our users to generate print-ready PDF documents using variable data (names, titles, phone numbers, etc) that their customer's enter via an online e-commerce website. To facilitate the variable data we have to embed a font's entire character map. On windows we have been using the windows API function GetFontData(...) like so:
#ifdef Q_WS_WIN
//this is windows specific code
HDC DC = CreateCompatibleDC(NULL);
HFONT hFont = font.handle();
HFONT oFont=(HFONT)SelectObject(DC,hFont);
DWORD fontLength = ::GetFontData(DC, 0, 0, 0, 0);
if(fontLength != GDI_ERROR)
{
fontData.GrowAllocation(fontLength);
if(::GetFontData(DC, 0, 0, fontData.GetBuffer(), fontLength) == GDI_ERROR)
{
fontData.Clear();
}
else
{
fontData.SetLength(fontLength);
returnVal = true;
}
}
SelectObject(DC,oFont);
DeleteDC(DC);
//End of windows specific code
#elif defined(Q_WS_MAC)
#endif
This technique works very successfully on our windows specific version; however, we are porting the application to Qt to target the Mac OSX platform.
My first question: Is there a Qt way of accessing the raw font data from a QFont, QFontDatabase, etc. that we could use to embed in the pdf? We have been unable to find a way. Notice the #ifdef wrapper in the above code. Note that the variable fontData is a self contained memory buffer that manages its own memory, please disregard.
My second question: If there is no Qt way of accessing the font data in an OS agnostic way, what is the OSX equivalent to the windows GetFontData?
Thanks
I've only skimmed documentation for GetFontData, and I don't know much about Qt (though it does sound like a Qt solution would be preferable), but you might want to look at the ObjC class for fonts, NSFont.
The latest (until Apple hires new font people and gets infected with not-invented-here disease again) text and font API is Core Text. I never used it since chasing Apple's mood is harmful to my personal and organization's financial health, I stopped using any Apple-only API. :)
Kidding aside, it looks like CTFont does provide access to all tables in a font. I don't see anything that prepares a font for embedding but this probably gives you the best chance.

visual c++ copy textbox content

how to copy textbox->Text content in a char array?
i m working in vc++.
Use CWnd::GetWindowText()
CString str;
CWnd* pWnd = GetDlgItem(IDC_WHATEVER);
pWnd->GetWindowText(str);
Puts the contents of the control into the CString or you can use the array version:
TCHAR sz[10];
int nRet = pWnd->GetWindowText(sz, 10);
Your query is unclear, so I'll have to assume things.
Assuming you are using MFC, add a control type variable to your edit box (say m_Edit), and use m_Edit.GetWindowText() to get the text.
Or if you're using plain Win32, use the GetWindowText() Win32 API.
On an additional note, like another user pointed out, stop using things like fixed-size character arrays to store strings if you are using c++. Use something like std::string or use CString if you're using MFC. By doing so, you can manipulate strings much easily and your code will be less error prone.
Cheers, Rajesh. MVP, Visual C++
You can also try like this.....
CString csTbxName;
GetDlgItemText(IDC_EDIT1,csTbxName);
const char* pchTbxName = csTbxName.GetBuffer();
char chTbxNameDup[5000];
ZeroMemory(chTbxNameDup,5000);
if(csTbxName.GetLength() < 5000)
{
memcpy(chTbxNameDup,(void*)pchTbxName,csTbxName.GetLength());
}