I'm developing an application to randomly change the users wallpaper at a specific time interval. Everything works as expected, except for the occasional error of 0 set by SystemParametersInfo(), which results in the wallpaper being reset to a black screen.
The 0 error is supposed to denote the operation was successful, yet that's obviously not the case. This error does not occur every time a new background is set, but randomly. I've searched this website and many others for possible solutions.. to no avail.
void setBackground() {
dirSize = FindMaxFileNum(); //Reads num of .jpg's in the folder.
if(dirSize != -1)
{
srand( (unsigned int)time(NULL));
bgChoice = rand() % dirSize + 1;
//Ensures backgrounds don't repeat.
for(int i=0; i<=2; i++)
{
if(lastBackground[i] == bgChoice)
{ bgChoice = rand() % dirSize + 1; }
}
//Tracks the last background used.
lastBackground[bgCount] = bgChoice;
bgCount++;
//Resets the counter so we can track the last 3 bg's used.
if(bgCount == 2)
{ bgCount = 0; }
}
else
{
dwLastError = GetLastError();
ssLastError << "Error: " << dwLastError << ".";
MessageBox(NULL, ssLastError.str().c_str(), "Error!", MB_ICONEXCLAMATION | MB_OK);
ssLastError.str("");
}
ssFilePath.str(""); //Ensures the stringstream is clean.
ssFilePath << strLocalDirectory << bgChoice << ".jpg";
if( SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID)ssFilePath.str().c_str(),
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE) != 0)
{
// Refresh the desktop - cleaning of PIDL is in the WM_DESTROY message.
SHGetSpecialFolderLocation(NULL,CSIDL_DESKTOP,&pidl);
SHChangeNotify(SHCNE_ASSOCCHANGED,SHCNF_IDLIST,pidl,0);
}
else
{
dwLastError = GetLastError();
ssLastError << "Error: " << dwLastError << ".";
MessageBox(NULL, ssLastError.str().c_str(), "Error!", MB_ICONEXCLAMATION | MB_OK);
ssLastError.str("");
}
}
Related
I am currently searching for a way to set a fully custom resolution on a Windows Server 2019 VM with GPU (T4, with grid licence, and virtual workstation grid drivers) with C++.
I have tried different way to achieve this, I can make this work on my laptop, but seems to have some limitations on GCP VMs (or Windows Server limitation).
I have tried to do this with ChangeDisplaySettings/ChangeDisplaySettingsEx (winuser.h), I can change to a known resolution, but can't make it works with a custom one (not even with CDS_ENABLE_UNSAFE_MODE).
DWORD deviceIndex = 0;
DISPLAY_DEVICE displayDevice = { 0 };
displayDevice.cb = sizeof(DISPLAY_DEVICE);
while (EnumDisplayDevices(NULL, deviceIndex, &displayDevice, 0)) {
deviceIndex++;
DEVMODE dm = { 0 };
dm.dmSize = sizeof(DEVMODE);
DEVMODE finalDm = { 0 };
finalDm.dmSize = sizeof(DEVMODE);
//Check if able to retrieve current settings
if (!EnumDisplaySettings(displayDevice.DeviceName, ENUM_CURRENT_SETTINGS, &dm)) {
continue;
}
//Check if there is a difference in resolution list if UNSAFE_MODE is enabled or not (it seems to not change anything)
int result = ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, 0, CDS_DISABLE_UNSAFE_MODES, NULL);
std::cout << "CDS_DISABLE_UNSAFE_MODE" << std::endl;
if (result == DISP_CHANGE_SUCCESSFUL) {
for (int i = 0; EnumDisplaySettings(displayDevice.DeviceName, i, &dm) != 0; i++) {
if (dm.dmBitsPerPel == 32) {
std::cout << i << ". Found available resolution : " << dm.dmPelsWidth << " x " << dm.dmPelsHeight << " x " << dm.dmBitsPerPel << " # " << dm.dmDisplayFrequency << std::endl;
}
}
}
result = ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, 0, CDS_ENABLE_UNSAFE_MODES, NULL);
std::cout << "CDS_ENABLE_UNSAFE_MODE" << std::endl;
if (result == DISP_CHANGE_SUCCESSFUL) {
for (int i = 0; EnumDisplaySettings(displayDevice.DeviceName, i, &dm) != 0; i++) {
if (dm.dmBitsPerPel == 32) {
std::cout << i << ". Found available resolution : " << dm.dmPelsWidth << " x " << dm.dmPelsHeight << " x " << dm.dmBitsPerPel << " # " << dm.dmDisplayFrequency << std::endl;
}
}
}
std::cout << "Please enter width : ";
int width, height;
std::cin >> width;
std::cout << "Please enter height : ";
std::cin >> height;
dm.dmPelsWidth = width;
dm.dmPelsHeight = height;
if (width > height) {
dm.dmDisplayOrientation = DMDO_DEFAULT;
}
else {
dm.dmDisplayOrientation = DMDO_90;
}
dm.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_DISPLAYORIENTATION;
//result = ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, NULL, CDS_TEST, NULL);
result = ChangeDisplaySettingsEx(displayDevice.DeviceName, &dm, NULL, 0, NULL);
if (result != DISP_CHANGE_SUCCESSFUL) {
std::cout << "Impossible to ChangeDisplaySettings" << endl;
}
else {
std::cout << "OK" << endl;
}
break;
}
I then take a look at NVAPI, and same here, I can make it works on my PC but still nothing on the GCP VMs... I have found a way to make NVAPI create and use custom resolution on my local PC, but can't make it works on GCP VM once again... (Code example found here)
NvAPI_Status result = NVAPI_ERROR;
NvU32 primaryDisplayId = 0;
//Testing resolution
int horizontal = 1920, vertical = 1090;
result = NvAPI_Initialize();
if (result != NVAPI_OK) {
printf("Could not initialize NvAPI");
return false;
}
MONITORINFOEX monInfo;
HMONITOR hMon;
const POINT ptZero = { 0, 0 };
// determine the location of the primary monitor
hMon = MonitorFromPoint(ptZero, MONITOR_DEFAULTTOPRIMARY);
ZeroMemory(&monInfo, sizeof(monInfo));
monInfo.cbSize = sizeof(monInfo);
GetMonitorInfo(hMon, &monInfo);
result = NvAPI_DISP_GetGDIPrimaryDisplayId(&primaryDisplayId);
if (result != NVAPI_OK) {
printf("Could not get display ID from device");
NvAPI_Unload();
return false;
}
NvU32 deviceCount = 0;
NV_CUSTOM_DISPLAY cd[NVAPI_MAX_DISPLAYS] = { 0 };
float refreshRate = 60;
// timing computation (to get timing that suits the changes made)
NV_TIMING_FLAG flag = { 0 };
NV_TIMING_INPUT timing = { 0 };
timing.version = NV_TIMING_INPUT_VER;
timing.height = vertical;
timing.width = horizontal;
timing.rr = refreshRate;
timing.flag = flag;
timing.type = NV_TIMING_OVERRIDE_CVT_RB;
result = NvAPI_DISP_GetTiming(primaryDisplayId, &timing, &cd[0].timing);
if (result != NVAPI_OK) {
printf("Failed to get timing for display"); // failed to get custom display timing
NvAPI_Unload();
return false;
}
cd[0].width = horizontal;
cd[0].height = vertical;
cd[0].xRatio = 1;
cd[0].yRatio = 1;
cd[0].srcPartition = { 0, 0, 1.0, 1.0 };
cd[0].depth = 32;
cd[0].version = NV_CUSTOM_DISPLAY_VER;
cd[0].colorFormat = NV_FORMAT_A8R8G8B8;
//Returns NVAPI_ERROR on GCP but NVAPI_OK on my laptop
result = NvAPI_DISP_TryCustomDisplay(&primaryDisplayId, 1, cd);
if (result != NVAPI_OK) {
printf("Could not set custom resolution");
NvAPI_DISP_RevertCustomDisplayTrial(&primaryDisplayId, 1);
NvAPI_Unload();
return false;
}
else {
NvAPI_DISP_SaveCustomDisplay(&primaryDisplayId, 1, true, true);
}
This part works perfectly well on my laptop, I can use a new dynamic resolution (It works with 1920x400, 1920x500, 1920x600), but not on my GCP VM, this parts :
NvAPI_DISP_TryCustomDisplay(&primaryDisplayId, 1, cd);
always returns NVAPI_ERROR
I have found another trick, I can edit this registry entry : HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Video{RANDOM_ID}\0001\NV_Modes
(Here is an old pdf, after some testing, it seems it is still working this way)
If I add some resolution using NVAPI, I can then set through ChangeDisplaySettingsEx function this resolution (it needs GPU driver restart, or Windows restart be able to change to a fresh new added resolution).
But I need to be able to rotate screen, playing with "dmDisplayOrientation", and it does not seem to work on GCP VM once again, if I authorize for example 1920x1090 I can set resolution to this, but cannot set 1090x1920 with a "dmDisplayOrientation = DMDO_90" (even if I authorize 1090x1920 too...)
So if anyone found a way, or have any idea on how to do this, it would be great, I am running out of idea right now...
I am trying to read the physical memory values in Hardware\ResourceMap\System Resources\Physical Memory using the following code:
#include <iostream>
#include <conio.h>
#include <windows.h>
#include <string>
#include <stdlib.h>
using namespace std;
int main()
{
HKEY hKey = NULL;
LPCTSTR pszSubKey = L"Hardware\\ResourceMap\\System Resources\\Physical Memory";
LPCTSTR pszValueName = L".Translated";
if (! RegOpenKey(HKEY_LOCAL_MACHINE, pszSubKey, &hKey) == ERROR_SUCCESS)
{
cout << "RegOpenKey failed" << endl;
return 0;
}
DWORD dwType = 0;
LPBYTE lpData = NULL;
DWORD dwLength = 0;
if (! RegQueryValueEx(hKey, pszValueName, 0, &dwType, NULL, &dwLength) == ERROR_SUCCESS)
{
cout << "RegOpenKey failed" << endl;
return 0;
}
lpData = new BYTE[dwLength];
RegQueryValueEx(hKey, pszValueName, 0, &dwType, lpData, &dwLength);
RegCloseKey(hKey);
DWORD dwResourceCount = *(DWORD*)(lpData + 16);
auto pmi = lpData + 24;
for (int dwIndex = 0; dwIndex < dwResourceCount; dwIndex++)
{
auto start = *(uint64_t*)(pmi + 0);
cout << "-> 0x" << hex << start;
auto length = *(uint64_t*)(pmi + 8);
cout << "\t + 0x" << hex << length;
auto endaddr = start + length;
cout << "\t0x" << hex << endaddr << endl;
pmi += 20;
}
delete[]lpData;
}
A sample output:
-> 0x1000 + 0x57000 0x58000
-> 0x59000 + 0x46000 0x9f000
-> 0x100000 + 0xc855f000 0xc865f000
-> 0xc8666000 + 0xbf3000 0xc9259000
-> 0xc9759000 + 0x13779000 0xdced2000
-> 0xdd0d8000 + 0x3c000 0xdd114000
-> 0xddfff000 + 0x1000 0xde000000
-> 0x100000000 + 0x41f0000 0x1041f0000
The problem is that the last length value is incorrect.
Instead of 0x41f0000, the Registry editor shows 0x41f000000 to be the correct value:
I have been researching this issue for the past few days, but cannot figure out why I get a false value here.
Can anyone with more experience using the Win32 API help me?
if value type is REG_RESOURCE_LIST value data is CM_RESOURCE_LIST structure. need use it instead of *(DWORD*)(lpData + 16);, lpData + 24. anyway your code is incorrect in case Count != 1. what you try print is CM_PARTIAL_RESOURCE_DESCRIPTOR structures. but you not check the Type member of CM_PARTIAL_RESOURCE_DESCRIPTOR. but it cab be different. can be CmResourceTypeMemory but also can be CmResourceTypeMemoryLarge - you not take this in account. in case CmResourceTypeMemoryLarge need check Flags for
CM_RESOURCE_MEMORY_LARGE_40
CM_RESOURCE_MEMORY_LARGE_48
CM_RESOURCE_MEMORY_LARGE_64
and
you say:
Instead of 0x41f0000 the regeditor shows 0x41f000000
but 0x41f000000 is shifted on 8 bit 0x41f0000. based on this obvious that you really have here CmResourceTypeMemoryLarge with CM_RESOURCE_MEMORY_40 flag.
in this case need use Length40 member:
The high 32 bits of the 40-bit length, in bytes, of the range of
allocated memory addresses. The lowest 8 bits are treated as zero.
so code for dump CM_RESOURCE_LIST must be next:
BOOL Memory(PCM_RESOURCE_LIST pcrl, ULONG size)
{
if (size < FIELD_OFFSET(CM_RESOURCE_LIST, List))
{
return FALSE;
}
size -= FIELD_OFFSET(CM_RESOURCE_LIST, List);
if (ULONG Count = pcrl->Count)
{
PCM_FULL_RESOURCE_DESCRIPTOR List = pcrl->List;
do
{
if (size < FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors))
{
return FALSE;
}
size -= FIELD_OFFSET(CM_FULL_RESOURCE_DESCRIPTOR, PartialResourceList.PartialDescriptors);
DbgPrint("InterfaceType=%x BusNumber=%u\n", List->InterfaceType, List->BusNumber);
if (ULONG n = List->PartialResourceList.Count)
{
PCM_PARTIAL_RESOURCE_DESCRIPTOR PartialDescriptors = List->PartialResourceList.PartialDescriptors;
do
{
if (size < sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR))
{
return FALSE;
}
size -= sizeof(CM_PARTIAL_RESOURCE_DESCRIPTOR);
ULONG64 Length = PartialDescriptors->u.Memory.Length;
switch (PartialDescriptors->Type)
{
case CmResourceTypeMemoryLarge:
switch (PartialDescriptors->Flags & (CM_RESOURCE_MEMORY_LARGE_40|
CM_RESOURCE_MEMORY_LARGE_48|CM_RESOURCE_MEMORY_LARGE_64))
{
case CM_RESOURCE_MEMORY_LARGE_40:
Length <<= 8;
break;
case CM_RESOURCE_MEMORY_LARGE_48:
Length <<= 16;
break;
case CM_RESOURCE_MEMORY_LARGE_64:
Length <<= 32;
break;
default:
DbgPrint("unknown mamory type\n");
continue;
}
case CmResourceTypeMemory:
DbgPrint("%016I64x %I64x\n",
PartialDescriptors->u.Memory.Start.QuadPart, Length);
break;
}
} while (PartialDescriptors++, --n);
}
} while (List++, --Count);
}
return size == 0;
}
also when we get it data - need not forget close key handle even on error (you not do this when RegQueryValueEx fail) and use RegOpenKeyExW instead RegOpenKey for ability specify the desired access rights to the key. the use 2 sequential calls to RegQueryValueEx (with 0 buffer and allocated once buffer) also not the best. because in theory buffer size can changed (some change value) between this 2 calls and you can fail got data on second call RegQueryValueExtoo. also we can already on first call allocate reasonable memory space, and only if it will be not enough - reallocate on next call. so better call this in loop until we got ERROR_MORE_DATA and first time call with already not empty buffer:
ULONG Memory()
{
HKEY hKey;
ULONG dwError = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
L"Hardware\\ResourceMap\\System Resources\\Physical Memory",
0, KEY_READ, &hKey);
if (dwError == NOERROR)
{
ULONG cb = 0x100;
do
{
dwError = ERROR_NO_SYSTEM_RESOURCES;
union {
PVOID buf;
PBYTE pb;
PCM_RESOURCE_LIST pcrl;
};
if (buf = LocalAlloc(0, cb))
{
ULONG dwType;
if ((dwError = RegQueryValueExW(hKey, L".Translated",
0, &dwType, pb, &cb)) == NOERROR)
{
if (dwType == REG_RESOURCE_LIST)
{
if (!Memory(pcrl, cb))
{
DbgPrint("error parsing resource list\n");
}
}
else
{
dwError = ERROR_INVALID_DATATYPE;
}
}
LocalFree(buf);
}
} while (dwError == ERROR_MORE_DATA);
RegCloseKey(hKey);
}
return dwError;
}
When I move my mouse or do any mouse related operations like clicking, it isn't picked up or read by ReadConsoleInput while keyboard events are picked up.
It used to work but now, I don't know what's causing problems which blocks the reading of mouse events.
This is the code i'm using, and I referred from This Website
DWORD numEvents = 0;
DWORD numEventsRead = 0;
while (appIsRunning)
{
reachedEnd = false;
GetNumberOfConsoleInputEvents(Input_Handle, &numEvents);
if (numEvents != 0)
{
INPUT_RECORD *eventBuffer = new INPUT_RECORD[numEvents];
ReadConsoleInput(Input_Handle, eventBuffer, numEvents, &numEventsRead);
for (DWORD i = 0; i < numEventsRead; ++i)
{
if (eventBuffer[i].EventType == KEY_EVENT) // this works
{
. // other
. // functions
if (eventBuffer[i].Event.KeyEvent.uChar.UnicodeChar == 'c' && eventBuffer[i].Event.KeyEvent.bKeyDown)
return true;
}
else if (eventBuffer[i].EventType == MOUSE_EVENT) // this doesnt work
{
cout << " E";
if (eventBuffer[i].Event.MouseEvent.dwButtonState == FROM_LEFT_1ST_BUTTON_PRESSED)
{
char x[50];
fstream file;
file.open("test.txt", ios::out);
cout << " YY";
SetConsoleCursorPosition(Output_Handle, { eventBuffer[i].Event.MouseEvent.dwMousePosition.X , eventBuffer[i].Event.MouseEvent.dwMousePosition.Y });
cin >> x;
file << "SetConsoleCursorPosition(out, { "
<< eventBuffer[i].Event.MouseEvent.dwMousePosition.X << " , "
<< eventBuffer[i].Event.MouseEvent.dwMousePosition.Y << "}); "
<< x;
}
}
}
delete[] eventBuffer;
}
if (reachedEnd)
return true;
}
I guess i should also post the code which sets the console mode and stuff
void initScr(COORD bufferSize, HANDLE& hOut, HANDLE& hIn, SMALL_RECT screen, SMALL_RECT side, Box& screenBox, Box& sideBox)
{
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
hIn = GetStdHandle(STD_INPUT_HANDLE);
CONSOLE_CURSOR_INFO cursorInfo;
SMALL_RECT windowSize = { 0, 0, bufferSize.X - 1, bufferSize.Y - 1 };
SetWindowPos(GetConsoleWindow(), HWND_TOPMOST, 5, 5, 0, 0, SWP_NOREDRAW | SWP_SHOWWINDOW | SWP_NOSIZE);
SetConsoleWindowInfo(hOut, true, &windowSize);
SetConsoleScreenBufferSize(hOut, bufferSize);
SetConsoleMode(hOut, ENABLE_WINDOW_INPUT | ENABLE_INSERT_MODE | ENABLE_EXTENDED_FLAGS | ENABLE_MOUSE_INPUT);
cls(hOut); //Clears the whole screen
SetConsoleTitle(L"The Game");
GetConsoleCursorInfo(hOut, &cursorInfo);
cursorInfo.bVisible = false;
SetConsoleCursorInfo(hOut, &cursorInfo);
screenBox.drawBox(screen, hOut, COLOR(bRed | bGreen | bBright ));
sideBox.drawBox(side, hOut, COLOR(bRed | bGreen | bBright));
setcursorPos({ 91, 5 }, hOut);
cout << "Press \'C\' to re-create maze";
setcursorPos({ 91, 7 }, hOut);
cout << " Arrow keys for movement.";
setcursorPos({ 0,0 }, hOut);
}
I guess this part of my code is quite messy.
Your problem is enabled selection by mouse in console.
just open your console (Win + r) -> cmd, open properties and disable highlighting function
(I have russian language as my default, but checkbox that you need must be here (i highlighted it by red line))
You may need to pass the ENABLE_MOUSE_INPUT flag to SetConsoleMode().
Also notice that some functions will discard console mouse events. Read the notes at the linked SetConsoleMode documentation.
I'd like to write a c++ program(windows console application) to print receipts from a server (via websocket) to a locally connected(via rs-232) receipt printer(NCR 7197 rev 1.0).
I got both the websocket connection and the serial handle operating and ready.
My problem is, that I can't find any example to guide me through the process of printing, or how to even begin. I mean, do I have to write some bytes or read any before I start passing the "document" to the printer, or do I need to write any config bytes, or anything.
If someone has any suggestions to where to start, or any example preferably in c++, I will be thankful.
I came across the solution that I developed way back than, while cleaning my old projects folder. Seeing the multiple hundred of views on this question, I wanted to post an answer. Here is my solution, but it might be outdated:
The function to connect to a device through a COM port:
// Serial port connection handle connect method
HANDLE connect_h(wchar_t* s_port, int s_flowcontrol, int s_baudrate, int s_bytesize, int s_stopbits, int s_parity) {
wchar_t* port = s_port;
std::wstring ws(port);
std::string port_w(ws.begin(), ws.end());
// Open serial port
HANDLE hSerial;
hSerial = CreateFile(port, GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if(hSerial == INVALID_HANDLE_VALUE) {
if(GetLastError() == ERROR_FILE_NOT_FOUND) {
// Serial port does not exist. Inform user.
std::cout << "Error: Serial port does not exists. Port: " << std::endl;
}
// Some other error occurred. Inform user.
std::cout << "Error: Cannot connect to port: " + port_w << std::endl;
std::cout << "Error code: " + GetLastError() << std::endl;
}
// Do some basic settings
DCB dcbSerialParams = { 0 };
dcbSerialParams.DCBlength = sizeof(dcbSerialParams);
if(!GetCommState(hSerial, &dcbSerialParams)) {
// Error getting state
std::cout << "Error: Cannot get port state. Port: " + port_w << std::endl;
std::cout << "Error code: " + GetLastError() << std::endl;
}
dcbSerialParams.BaudRate = s_baudrate;
dcbSerialParams.ByteSize = s_bytesize;
dcbSerialParams.StopBits = s_stopbits;
dcbSerialParams.Parity = s_parity;
// If flowcontrol set to XON/XOFF
if(s_flowcontrol == 1) {
dcbSerialParams.fDtrControl = DTR_CONTROL_DISABLE;
dcbSerialParams.fRtsControl = RTS_CONTROL_DISABLE;
dcbSerialParams.fOutX = true;
dcbSerialParams.fInX = true;
dcbSerialParams.XonChar = 0x11;
dcbSerialParams.XoffChar = 0x16;
}
if(!SetCommState(hSerial, &dcbSerialParams)) {
// error setting serial port state
std::cout << "Error: Cannot set port state. Port: " + port_w << std::endl;
std::cout << "Error code: " + GetLastError() << std::endl;
}
// Set timeouts
COMMTIMEOUTS timeouts = { 0 };
timeouts.ReadIntervalTimeout = 50;
timeouts.ReadTotalTimeoutConstant = 50;
timeouts.ReadTotalTimeoutMultiplier = 10;
timeouts.WriteTotalTimeoutConstant = 50;
timeouts.WriteTotalTimeoutMultiplier = 10;
if (!SetCommTimeouts(hSerial, &timeouts)) {
// Error occureed. Inform user
std::cout << "Error: Cannot set port timeouts. Port: " + port_w << std::endl;
std::cout << "Error code: " + GetLastError() << std::endl;
}
return hSerial;
}
Closing the serial port connection:
// Serial port connection handle close method
void close_h(const HANDLE &hSerial) {
CloseHandle(hSerial);
}
The function to print through the connected COM port:
// Printing recipe via serial port handle
std::string set_print(const HANDLE &hSerial, std::string &document) {
std::string result = "";
std::string printable = "";
// Format flags
bool _bold_flag = false;
bool _underline_flag = false;
bool _italic_flag = false;
// Process document for printing
for(int i = 0; i < (int)document.length(); ++i) {
if(document[i] == '\\') {
switch (document[i + 1]) {
// new line
case 'n':
printable.push_back((char)(0x0A));
i++;
break;
// underline format begin/end
case 'u':
if(!_underline_flag) {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x2D));
printable.push_back('1');
_underline_flag = true;
}
else {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x2D));
printable.push_back('0');
_underline_flag = false;
}
i++;
break;
// bold format begin/end
case 'b':
if (!_bold_flag) {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x47));
printable.push_back('1');
_bold_flag = true;
}
else {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x47));
printable.push_back('0');
_bold_flag = false;
}
i++;
break;
// italic format begin/end
case 'i':
if (!_italic_flag) {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x49));
printable.push_back('1');
_italic_flag = true;
}
else {
printable.push_back((char)(0x1B));
printable.push_back((char)(0x49));
printable.push_back('0');
_italic_flag = false;
}
i++;
break;
// if not recognized
default:
printable.push_back(document[i]);
break;
}
}
else {
printable.push_back(document[i]);
}
}
// Additional push
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
printable.push_back((char)(0x0A));
// Add EOF bytes
printable.push_back((char)(0x03));
printable.push_back((char)(0x04));
// Add knife cut command
printable.push_back((char)(0x19));
printable.push_back((char)(0x1B));
printable.push_back((char)(0x76));
// Convert to hexadecimal
int* hex_print = new int[printable.length()];
for(int i = 0; i < (int)printable.length(); ++i) {
hex_print[i] = (int)printable[i];
}
// Print
for(int i = 0; i < (int)printable.length(); ++i) {
int rq[1] = { hex_print[i] };
DWORD rqBytesWritten = 0;
if(!WriteFile(hSerial, rq, 1, &rqBytesWritten, NULL)) {
// error occurred. Report to user.
std::cout << "Error: Can't write byte. written: " + rqBytesWritten << std::endl;
}
}
// return status
return result;
}
And a test main function, to demonstrate the usage of these functions:
// MAIN()
int main(int argc, char* argv[]) {
// Create connection on COM port 1
HANDLE sh_printer = connect_h(L"COM1", 0, 38400);
// Print a string povided in first argument
set_print(sh_printer, args[1]);
// Close the COM port connection
close_h(sh_printer);
return 0;
}
I hope I could be of any help to anyone, who tires to use this ancient way of printing a receipt. :)
I am trying to enable a secondary monitor in C++. What I have seems to try and change the display settings but nothing really happens, can anyone tell me where I am going wrong?
std::wstring devName( L"Intel(R) HD Graphics Family" );
std::wstring dispName( L"\\\\.\\DISPLAY3" );
DISPLAY_DEVICE theDisplay;
theDisplay.cb = sizeof(theDisplay);
DWORD dev = 0;
while(EnumDisplayDevices(0, dev, &theDisplay, 0))
{
if (devName.compare(theDisplay.DeviceString) == 0 && dispName.compare(theDisplay.DeviceName) == 0)
{
// found display adapter we're looking for
if (theDisplay.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
{
// Display is part of desktop, turn al other monitors off
cout << "Display is part of desktop\n";
}
else
{
// Display is off, turn it on
DEVMODE dm;
memset(&dm,0,sizeof(DEVMODE));
dm.dmSize = sizeof (DEVMODE);
dm.dmFields = DM_POSITION;
dm.dmPosition.x = 3361;
dm.dmPosition.y = 0;
dm.dmPelsWidth = 1920;
dm.dmPelsHeight = 1080;
LONG ret = ChangeDisplaySettingsEx (theDisplay.DeviceName, &dm, NULL, CDS_UPDATEREGISTRY, NULL);
if (ret != DISP_CHANGE_SUCCESSFUL)
{
cout << "failed";
}
}
}
dev++;
}
system ("pause");
return 0;