Can I localize AFX_IDP_ASK_TO_SAVE? - c++

In my application, I have a 'Do you want to save your changes?' message box. I'm getting the text to display from MFC:
CString prompt;
AfxFormatString1(prompt, AFX_IDP_ASK_TO_SAVE, strFileName);
UINT nResult = AfxMessageBox(prompt, MB_YESNOCANCEL, AFX_IDP_ASK_TO_SAVE)
Now I'm localizing the application to Japanese. I'm guessing that standard texts such as this are already translated to most of the major languages. But I have no idea how to set MFC to use the Japanese versions of the resource identifiers of these standard texts. Is it possible to do this?

It turned out I needed to change a few include files in my .rc file:
#include "afxres.rc" // Standard components
#include "afxprint.rc" // printing/print preview resources
#include "afxribbon.rc" // MFC ribbon and control bar resources
needed to become:
#include "l.jpn/afxres.rc" // Standard components
#include "l.jpn/afxprint.rc" // printing/print preview resources
#include "l.jpn/afxribbon.rc" // MFC ribbon and control bar resources

In VS2008 AFX_IDP_ASK_TO_SAVE and other AFX_... strings are kept in MFC localization DLLs: MFC90CHS.dll, MFC90JPN.dll. MFC90KOR.dll etc. To use them on Windows Vista and later you should call:
SetThreadUILanguage (MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US));
or
SetThreadUILanguage (MAKELANGID(LANG_JAPANESE,SUBLANG_JAPANESE_JAPAN));
on Windows XP call:
SetThreadLocale(lcid)
For constants refer to https://msdn.microsoft.com/en-us/library/windows/desktop/dd318693%28v=vs.85%29.aspx
Use GetSystemDefaultLangID to retrieve right locale i.e. on Chinese OS.
Important: don't use GetUserDefaultLangID() or GetSystemDefaultUILanguage(), they return different things, i.e. in case you have English OS, having Chinese locale selected.
lcid = MAKELCID(GetSystemDefaultLangID(), SORT_DEFAULT);//With Chinese locale, returns 0x804, zh-CN

Related

Why do I need a QTranslator for localized button texts in a QMessageBox on Windows?

I'm developing a Qt application that runs on Linux and Windows. I'm on a German locale.
When building it on Linux, I get the correct translations for the standard buttons displayed by e. g. a QMessageBox::question with QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel buttons set ("Ja", "Nein" and "Abbrechen" in my case).
If I build the code on Windows however, I only get the C locale (English) texts for those buttons ("Yes", "No" and "Cancel").
After some searching, I found a globally working solution by adding
#include <QTranslator>
#include <QLibraryInfo>
and
QTranslator qtTranslator;
if (qtTranslator.load(QLocale::system(), QString::fromUtf8("qt"), QString::fromUtf8("_"),
QLibraryInfo::location(QLibraryInfo::TranslationsPath))) {
app.installTranslator(&qtTranslator);
}
to my main.cpp.
Using this, I also get the translated strings on Windows. On Linux however, the qtTranslator.load call fails and thus, nothing happens to the state I had before, so I ended up putting that code inside an #ifdef Q_OS_WIN block.
This works, but seems a bit hacky to me. Plus, I don't understand why I get the translated strings on Linux by default and not on Windows.
Is the way I do it the correct solution? And if so, why do I need that additional code on Windows?
Try to replace your code on this and tested.
static QTranslator qtTr;
qtTr.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
installTranslator(&qtTr);

Setting wxTE_PASSWORD later

I created two wxTextCtrl. One for log in (loginTxt) and another for password (pwdTxt) and both have readable default message.
I also installed wxEVT_LEFT_DOWN event so that when user click on either loginTxt or pwdTxt the default message will be set to empty string
Is it possible to set wxTE_PASSWORD style to the pwdTxt later? If it's possible, how can I do that?
I read wx.chm and it say,
"Note that alignment styles (wxTE_LEFT, wxTE_CENTRE and wxTE_RIGHT) can be changed dynamically after control creation on wxMSW and wxGTK. wxTE_READONLY, wxTE_PASSWORD and wrapping styles can be dynamically changed under wxGTK but not wxMSW. The other styles can be only set during control creation.".
I am writing my application on MS Windows with wxWidgets 2.9.3
You cannot change it later on Windows, since Microsoft's control does not support that. If you really need to, I suggest creating 2 different controls and show/hide the appropriate one.
Windows-only solution, probably will be useful:
void Sample::OnBUTTONClick( wxCommandEvent& event )
{
#if defined(__WXMSW__)
HWND hWnd = (HWND)m_Text->GetHandle();
SendMessage(hWnd, EM_SETPASSWORDCHAR, 0x25cf, 0); // 0x25cf is ● character
m_Text->Update();
#endif
}

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.

Removing exe from windows startmenu quick launch

For work we have two shortcuts that get installed to the start menu with both of them pointing to the same exe (but the second with different command line arguments).
Some times windows will pick the second shortcut to display in the start menu hot program list which is bad because it causes a full update of the application.
Is there a way to tell windows not to show that shortcut in the start menu list?
Yes, in fact Raymond Chen just wrote about this:
You can set the System.App­User­Model.Exclude­From­Show­In­New­Install property to VARIANT_TRUE to tell the Start menu, "I am not the primary entry point for the program; I'm a secondary shortcut, like a help file."
Sample code (CCoInitialize class):
#include <windows.h>
#include <tchar.h>
#include <shlobj.h>
#include <atlbase.h>
// class 3CCoInitialize incorporated here by reference
int __cdecl _tmain(int argc, TCHAR **argv)
{
// error checking elided for expository purposes
CCoInitialize init;
CComPtr<IShellLink> spsl;
spsl.CoCreateInstance(CLSID_ShellLink);
spsl->SetPath(TEXT("C:\\Program Files\\LitWare\\LWUpdate.exe"));
PROPVARIANT pvar;
pvar.vt = VT_BOOL;
pvar.boolVal = VARIANT_TRUE;
CComQIPtr<IPropertyStore>(spsl)->SetValue(PKEY_AppUserModel_ExcludeFromShowInNewInstall, pvar);
CComQIPtr<IPersistFile>(spsl)->Save(L"LitWare Update.lnk", TRUE);
return 0;
}
You'll find the documentation for those settings here: Application User Model IDs (AppUserModelIDs). Specifically, you're looking for the section entitled "Exclusion Lists for Taskbar Pinning and Recent/Frequent Lists". The applicable portion is reprinted below:
Applications, processes, and windows can choose to make themselves unavailable for pinning to the taskbar or for inclusion in the Start menu's MFU list. There are three mechanisms to accomplish this:
Add the NoStartPage entry to the application's registration as shown here:
HKEY_CLASSES_ROOT\Applications\Example.exe\NoStartPage
The data associated with the NoStartPage entry is ignored. Only the presence of the entry is required. Therefore, the ideal type for NoStartPage is REG_NONE.
Note that any use of an explicit AppUserModelID overrides the NoStartPage entry. If an explicit AppUserModelID is applied to a shortcut, process, or window, it becomes pinnable and eligible for the Start menu MFU list.
Set the System.AppUserModel.PreventPinning property on windows and shortcuts. This property must be set on a window before the PKEY_AppUserModel_ID property.
Add an explicit AppUserModelID as a value under the following registry subkey as shown here:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\FileAssociation\NoStartPageAppUserModelIDs\AppUserModelID
Each entry is a REG_NULL value with the name of the AppUserModelID. Any AppUserModelID found in this list is not pinnable and not eligible for inclusion in the Start menu MFU list.

Why isn't the dropdown arrow drawn for an CMFCMenuButton?

I ran into this issue when trying to add a CMFCMenuButton to an existing MFC application. It worked properly, and even resized the button to accommodate the dropdown arrow. But it didn't draw the dropdown arrow, and when I hovered over the button, I saw the following debug output:
> Can't load bitmap: 42b8.GetLastError() = 716
> CMenuImages. Can't load menu images 3f01
It turns out that even with Visual Studio 2010 RTM, when you create a brand new MFC Dialog based application, the CMFCMenuButton doesn't draw the arrow and shows the same errors. Initially I assumed that I didn't have something installed or registered correctly. However, the NewControls example from the MFC Feature Pack showed the dropdown arrow perfectly.
What is missing?
The reason I posted this question is because I couldn't find any answers via Google. The closest I came when researching it was a couple hacks that didn't seem to be the real solution. After pouring over the NewControls example, I finally found the culprit.
At the bottom of the default .rc file for a project, there is the following code:
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
#include "res\YOUR_PROJECT_NAME.rc2" // non-Microsoft Visual C++ edited resources
#include "afxres.rc" // Standard components
#endif
The NewControls example's .rc file looks like this:
#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU)
LANGUAGE 9, 1
#include "res\NewControls.rc2" // non-Microsoft Visual C++ edited resources
#include "afxres.rc" // Standard components
#ifndef _AFXDLL
#include "afxribbon.rc" // Ribbon and control bars
#endif
#endif
Adding the afxribbon.rc enables the bitmap resources needed for the controls in the MFC Feature pack update. Now you can't just simply add the missing code to the bottom of the .rc file. If you do that, every time you edit the resource file using the visual designer, your added code will be removed. The solution to the problem is to add this to the bottom of the YOUR_PROJECT_NAME.rc2 file:
#ifndef _AFXDLL
#include "afxribbon.rc" // Ribbon and control bars
#endif
Make sure you have an empty line at the bottom of the file, or the resource compiler will complain. I'm not sure what setting needs to be adjusted in order for the visual designer to automatically include afxribbon.rc like it does in the NewControls example project. But adding it to the .rc2 seems to fix the problem.
Update
Keep in mind that you can use the IDE to modify your RC file:
Right-Click the RC file and select Resource Includes...:
Paste the new code into the Compile-time directives area:
I solve this problem for myself in such way: I add a clause to CMyApp::InitInstance:
BOOL CMyApp::InitInstance()
{
CWinAppEx::InitInstance();
InitCommonControls();
//This!
CMFCVisualManager::SetDefaultManager(RUNTIME_CLASS(CMFCVisualManagerWindows));
//...
return TRUE;
}