Reputation: 41
I'm making a program using Win32 api and I have an edit control for the user to type in. I have created buttons with the idea being that the user can click these buttons to use super/subscript, and deactivate them when finished, but i'm struggling to actually implement them. I figured that I could create a new HFONT that was smaller, but when I send the WM_SETFONT message it changes all the text, so everything is small, and then everything is full size again when I disable it.
How can I change the font for the next characters typed, but not all the text in the control?
Upvotes: 0
Views: 455
Reputation: 1450
Hey try this to set the format:
void Subscript(HWND hWindow) {
CHARFORMAT2 cf;
cf.cbSize = sizeof(cf);
cf.dwMask = CFE_SUBSCRIPT;
cf.dwEffects = CFE_SUBSCRIPT;
SendMessage(hWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
}
void Superscript(HWND hWindow) {
CHARFORMAT2 cf;
cf.cbSize = sizeof(cf);
cf.dwMask = CFM_SUPERSCRIPT;
cf.dwEffects = CFM_SUPERSCRIPT;
SendMessage(hWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
}
...and this to reset it:
void ResetSuperSubScript(HWND hWindow) {
CHARFORMAT2 cf;
cf.cbSize = sizeof(cf);
cf.dwMask = CFM_SUPERSCRIPT | CFM_SUBSCRIPT;
cf.dwEffects = 0;
SendMessage(hWindow, EM_SETCHARFORMAT, SCF_SELECTION, (LPARAM)&cf);
}
Upvotes: 0
Reputation: 6299
As @IInspectable said that, use RichEdit is a good choice.
In addition, if you need to implement superscript and subscript functions, you can use SendInput to simulate keyboard keystroke.
SendInput: Synthesizes keystrokes, mouse motions, and button clicks.
Such as:
Superscript => Ctrl + Shift + '='
Subscript => Ctrl + '='
Simulation effect:
Code sample:
// Test_RichEdit.cpp : Defines the entry point for the application.
//
#include "stdafx.h"
#include "Test_RichEdit.h"
#include <Richedit.h>
#define MAX_LOADSTRING 100
// Global Variables:
HINSTANCE hInst; // current instance
WCHAR szTitle[MAX_LOADSTRING]; // The title bar text
WCHAR szWindowClass[MAX_LOADSTRING]; // the main window class name
HWND superscript_style;
HWND subscript_style;
HWND hwndEdit;
HWND deactivate;
// Forward declarations of functions included in this code module:
ATOM MyRegisterClass(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE, int);
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
INT_PTR CALLBACK About(HWND, UINT, WPARAM, LPARAM);
HWND CreateRichEdit(HWND hwndOwner, // Dialog box handle.
int x, int y, // Location.
int width, int height, // Dimensions.
HINSTANCE hinst); // Application or DLL instance.
void Superscript_style();
void Subscript_style();
int APIENTRY wWinMain(_In_ HINSTANCE hInstance,
_In_opt_ HINSTANCE hPrevInstance,
_In_ LPWSTR lpCmdLine,
_In_ int nCmdShow)
{
UNREFERENCED_PARAMETER(hPrevInstance);
UNREFERENCED_PARAMETER(lpCmdLine);
// TODO: Place code here.
// Initialize global strings
LoadStringW(hInstance, IDS_APP_TITLE, szTitle, MAX_LOADSTRING);
LoadStringW(hInstance, IDC_TESTRICHEDIT, szWindowClass, MAX_LOADSTRING);
MyRegisterClass(hInstance);
// Perform application initialization:
if (!InitInstance (hInstance, nCmdShow))
{
return FALSE;
}
HACCEL hAccelTable = LoadAccelerators(hInstance, MAKEINTRESOURCE(IDC_TESTRICHEDIT));
MSG msg;
// Main message loop:
while (GetMessage(&msg, nullptr, 0, 0))
{
if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return (int) msg.wParam;
}
//
// FUNCTION: MyRegisterClass()
//
// PURPOSE: Registers the window class.
//
ATOM MyRegisterClass(HINSTANCE hInstance)
{
WNDCLASSEXW wcex;
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_TESTRICHEDIT));
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
wcex.lpszMenuName = MAKEINTRESOURCEW(IDC_TESTRICHEDIT);
wcex.lpszClassName = szWindowClass;
wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_SMALL));
return RegisterClassExW(&wcex);
}
//
// FUNCTION: InitInstance(HINSTANCE, int)
//
// PURPOSE: Saves instance handle and creates main window
//
// COMMENTS:
//
// In this function, we save the instance handle in a global variable and
// create and display the main program window.
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
hInst = hInstance; // Store instance handle in our global variable
HWND hWnd = CreateWindowW(szWindowClass, szTitle, WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, nullptr, nullptr, hInstance, nullptr);
CreateRichEdit(hWnd, 50,50,200,200, hInst);
superscript_style = CreateWindowW(L"BUTTON",
L"Superscript",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS | WS_TABSTOP,
400, 60, 80, 30,
hWnd, (HMENU)1, NULL, NULL);
subscript_style = CreateWindowW(L"BUTTON",
L"Subscript",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS | WS_TABSTOP,
400, 130, 80, 30,
hWnd, (HMENU)2, NULL, NULL);
deactivate = CreateWindowW(L"BUTTON",
L"deactivate",
WS_CHILD | WS_VISIBLE | BS_DEFPUSHBUTTON | WS_CLIPSIBLINGS | WS_TABSTOP,
400, 200, 80, 30,
hWnd, (HMENU)3, NULL, NULL);
if (!hWnd)
{
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);
return TRUE;
}
//
// FUNCTION: WndProc(HWND, UINT, WPARAM, LPARAM)
//
// PURPOSE: Processes messages for the main window.
//
// WM_COMMAND - process the application menu
// WM_PAINT - Paint the main window
// WM_DESTROY - post a quit message and return
//
//
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static bool flag_sup = false;
static bool flag_sub = false;
switch (message)
{
case WM_COMMAND:
{
int wmId = LOWORD(wParam);
// Parse the menu selections:
switch (wmId)
{
case IDM_ABOUT:
DialogBox(hInst, MAKEINTRESOURCE(IDD_ABOUTBOX), hWnd, About);
break;
case IDM_EXIT:
DestroyWindow(hWnd);
break;
case 1:
{
flag_sup = true;
Superscript_style();
break;
}
case 2:
{
flag_sub = true;
Subscript_style();
break;
}
case 3:
{
if (flag_sup == true)
{
flag_sup = false;
Superscript_style();
}
else if (flag_sub == true)
{
flag_sub = false;
Subscript_style();
}
else
{
SetFocus(hwndEdit);
}
break;
}
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
}
break;
case WM_PAINT:
{
PAINTSTRUCT ps;
HDC hdc = BeginPaint(hWnd, &ps);
// TODO: Add any drawing code that uses hdc here...
EndPaint(hWnd, &ps);
}
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
// Message handler for about box.
INT_PTR CALLBACK About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
UNREFERENCED_PARAMETER(lParam);
switch (message)
{
case WM_INITDIALOG:
return (INT_PTR)TRUE;
case WM_COMMAND:
if (LOWORD(wParam) == IDOK || LOWORD(wParam) == IDCANCEL)
{
EndDialog(hDlg, LOWORD(wParam));
return (INT_PTR)TRUE;
}
break;
}
return (INT_PTR)FALSE;
}
HWND CreateRichEdit(HWND hwndOwner, // Dialog box handle.
int x, int y, // Location.
int width, int height, // Dimensions.
HINSTANCE hinst) // Application or DLL instance.
{
LoadLibrary(TEXT("Msftedit.dll"));
hwndEdit = CreateWindowEx(0, MSFTEDIT_CLASS, TEXT(""),
ES_MULTILINE | WS_VISIBLE | WS_CHILD | WS_BORDER | WS_TABSTOP,
x, y, width, height,
hwndOwner, NULL, hinst, NULL);
return hwndEdit;
}
void Superscript_style()
{
INPUT input[3];
memset(input, 0, sizeof(input));
input[0].type = input[1].type = input[2].type = INPUT_KEYBOARD;
SetFocus(hwndEdit);
input[0].ki.wVk = VK_CONTROL;
input[1].ki.wVk = VK_SHIFT;
input[2].ki.wVk = VK_OEM_PLUS;
SendInput(3, input, sizeof(INPUT));
input[0].ki.dwFlags = input[1].ki.dwFlags = input[2].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(3, input, sizeof(INPUT));
}
void Subscript_style()
{
INPUT input[2];
memset(input, 0, sizeof(input));
input[0].type = input[1].type = INPUT_KEYBOARD;
SetFocus(hwndEdit);
input[0].ki.wVk = VK_CONTROL;
input[1].ki.wVk = VK_OEM_PLUS;
SendInput(2, input, sizeof(INPUT));
input[0].ki.dwFlags = input[1].ki.dwFlags = KEYEVENTF_KEYUP;
SendInput(2, input, sizeof(INPUT));
}
Note:
If you're not familiar with SendInput
, you can refer this for more details.
Upvotes: 0
Reputation: 51499
You cannot. An EDIT control has a single font for all of its text. It does not allow you to apply formatting to portions of text. It's all or nothing.
If you want formatting, you'll need to use a more complex control, like a Rich Edit control.
Upvotes: 1