The line spacing cannot be changed with the source code below.
I would appreciate it if you could tell me how to create the LSpaceA()
and LSpaceB()
functions in the code below to change the line spacing.
Also, is the line LoadLibrary("riched20.dll")
needed?
This is a slightly modified code obtained from a question on ChatGPT. Compiled in DevC++.
When compiling in Visual Studio, various errors related to strcat
and sprintf
occur, so I have no choice but to test in DevC++.
Originally, I was looking for a way to change line spacing without using RichEdit, but I couldn't find a way without using RichEdit, so I'm going to use RichEdit, but it's hard to find samples on the Internet to test whether RichEdit works properly.
Even if you test by changing the variable value such as bLineSpacingRule
in the LSpaceA()
and LSpaceB()
functions in the code below, there is no change in line spacing at all.
#include <stdio.h>
#include <windows.h>
#include <richedit.h>
#define ID_EDIT 1
#define ID_BUTTON 2
HWND hEdit, hButton;
HINSTANCE hInstance;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
char sbuf[900];
void MkBuf()
{
char sta[300];
int ii;
strcpy(sbuf,"");
for(ii=0; ii<6; ii++){
sprintf(sta,"%dth line Test WinApi Test WinApi Test WinApi Test WinApi Test WinApi%c%c", 1+ii,0xD,0xA);
strcat(sbuf,sta);
}
}
void LSpaceA()
{
PARAFORMAT2 pf2;
pf2.cbSize = sizeof(PARAFORMAT2);
//SendMessage(hEdit, EM_GETPARAFORMAT, 0, (LPARAM)&pf2);
pf2.dwMask = PFM_LINESPACING;
//pf2.dwMask = PFM_SPACEBEFORE;
//pf2.bLineSpacingRule = 4;
pf2.dyLineSpacing = 400; // (!)
SendMessage(hEdit, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
}
void LSpaceB(HWND hwnd, int space)
{
PARAFORMAT2 pf;
pf.cbSize = sizeof(PARAFORMAT2);
pf.dwMask = PFM_LINESPACING;
pf.dyLineSpacing = space;
pf.bLineSpacingRule = 5; // (!)
SendMessage(hwnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
LoadLibrary("riched20.dll"); // for using rich edit
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = "EditorWindowClass";
RegisterClassEx(&wc);
HWND hwnd = CreateWindowEx(0, "EditorWindowClass", "Text Editor", WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL);
hEdit = CreateWindowEx(0, "EDIT", "", WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE,
0, 0, 800, 500, hwnd, (HMENU)ID_EDIT, hInstance, NULL);
hButton = CreateWindowEx(0, "BUTTON", "Change Line Spacing", WS_CHILD | WS_VISIBLE,
10, 510, 150, 30, hwnd, (HMENU)ID_BUTTON, hInstance, NULL);
MkBuf();
SetWindowText(hEdit, sbuf);
LSpaceA();
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_COMMAND:
if (LOWORD(wParam) == ID_BUTTON) {
LSpaceB(hEdit, 20);
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}
Your WinMain()
is creating a standard Edit control, not a RichEdit control. That is why your functions are not working, since the Edit control does not support the EM_SETPARAFORMAT
message. See How to Create Rich Edit Controls on MSDN.
You need to change the class name "EDIT"
to "RichEdit20A"
instead (ie, use the RICHEDIT_CLASS
constant defined in <Richedit.h>
), as you are using Riched20.dll
(see Versions of Rich Edit for more info).
//hEdit = CreateWindowEx(0, "EDIT", ...);
hEdit = CreateWindowEx(0, RICHEDIT_CLASS, ...);
On a side note: your creation and setup of the hEdit
and hButton
control should be moved inside of your WindowProc()
in a WM_CREATE
handler.
Try this:
#include <stdio.h>
#include <windows.h>
#include <richedit.h>
#include <tchar.h>
#define ID_EDIT 1
#define ID_BUTTON 2
HWND hEdit, hButton;
HINSTANCE hInstance;
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
TCHAR sbuf[900];
void MkBuf()
{
TCHAR sta[300];
int ii;
_tcscpy(sbuf, _T(""));
for(ii=0; ii<6; ii++){
_stprintf(sta, _T("%dth line Test WinApi Test WinApi Test WinApi Test WinApi Test WinApi\r\n"), 1+ii);
_tcscat(sbuf,sta);
}
}
void LSpaceA()
{
PARAFORMAT2 pf2;
pf2.cbSize = sizeof(PARAFORMAT2);
//SendMessage(hEdit, EM_GETPARAFORMAT, 0, (LPARAM)&pf2);
pf2.dwMask = PFM_LINESPACING;
//pf2.dwMask = PFM_SPACEBEFORE;
//pf2.bLineSpacingRule = 4;
pf2.dyLineSpacing = 400; // (!)
SendMessage(hEdit, EM_SETPARAFORMAT, 0, (LPARAM)&pf2);
}
void LSpaceB(HWND hwnd, int space)
{
PARAFORMAT2 pf;
pf.cbSize = sizeof(PARAFORMAT2);
pf.dwMask = PFM_LINESPACING;
pf.dyLineSpacing = space;
pf.bLineSpacingRule = 5; // (!)
SendMessage(hwnd, EM_SETPARAFORMAT, 0, (LPARAM)&pf);
}
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
LoadLibrary(TEXT("riched20.dll")); // for using rich edit
// alternatively, load "Msftedit.dll" instead for RichEdit 4.1+...
WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.style = CS_HREDRAW | CS_VREDRAW;
wc.lpfnWndProc = WindowProc;
wc.hInstance = hInstance;
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.lpszClassName = TEXT("EditorWindowClass");
RegisterClassEx(&wc);
HWND hwnd = CreateWindowEx(0, TEXT("EditorWindowClass"), TEXT("Text Editor"), WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT, 800, 600, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, nCmdShow);
UpdateWindow(hwnd);
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
return (int)msg.wParam;
}
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
switch (uMsg) {
case WM_CREATE: {
// alternatively, use MSFTEDIT_CLASS for RichEdit 4.1+...
hEdit = CreateWindowEx(0, RICHEDIT_CLASS, TEXT(""), WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE,
0, 0, 800, 500, hwnd, (HMENU)ID_EDIT, NULL, NULL);
hButton = CreateWindowEx(0, TEXT("BUTTON"), TEXT("Change Line Spacing"), WS_CHILD | WS_VISIBLE,
10, 510, 150, 30, hwnd, (HMENU)ID_BUTTON, NULL, NULL);
MkBuf();
SetWindowText(hEdit, sbuf);
LSpaceA();
break;
}
case WM_COMMAND:
if (LOWORD(wParam) == ID_BUTTON) {
LSpaceB(hEdit, 20);
}
break;
case WM_CLOSE:
DestroyWindow(hwnd);
break;
case WM_DESTROY:
PostQuitMessage(0);
break;
default:
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
return 0;
}