How to change the windows 10 wallpaper with C++? - c++

I am looking to change the Windows desktop background wallpaper in C++ using the Windows API.
I have read the following posts on this topic:
How to change desktop background using VC++
SystemParametersInfo sets wallpaper completly black (using SPI_SETDESKWALLPAPER)
Problem:
When I execute the code, the desktop background changes to completely black like in the post above (yes, I did try the suggested fix in that post. No luck.)
Code:
#include <windows.h>
int main() {
std::string s = "C:\\picture.jpg";
SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (PVOID*)s.c_str(), SPIF_SENDCHANGE);
return 0;
}
I have also tried just (void*) instead of (PVOID*) above and an L in front of the string. Nothing works so far.
SOLVED:
Changing SystemParametersInfo to SystemParametersInfoA (as suggested in the comment and answer) did the trick.

I believe you should use a wchar_t as input for SystemParametersInfo() instead of a string and also use SystemParametersInfoW().
The following code worked for me:
#include <windows.h>
#include <iostream>
int main() {
const wchar_t *path = L"C:\\image.png";
int result;
result = SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (void *)path, SPIF_UPDATEINIFILE);
std::cout << result;
return 0;
}
Where result should return true if it manages to change the background.

Related

Change input method on windows using c++ and windows API

I want to write some code in C++ in combination with windows API in order to change the input method on windows (Keyboard input language).
Here is my first try:
#include <iostream>
#include <windows.h>
int main() {
int arr_size = GetKeyboardLayoutList(0, NULL);
HKL hkl_array[arr_size]; // The array to hold input locale identifies found in the system(HKL)
// Initialize the array to all zeros
for (int i = 0; i <= arr_size - 1; i++) {
hkl_array[i] = nullptr;
}
int lang_found = GetKeyboardLayoutList(arr_size, hkl_array); // Get all the HKLs in the array
for (int i = 0; i <= lang_found - 1; ++i) {
// Print all the HKLs found
std::cout << i + 1 << ". " << hkl_array[i] << std::endl;
}
std::cout << "Function return: " << ActivateKeyboardLayout(hkl_array[0], KLF_SETFORPROCESS);
return 0;
}
When running the above code with English as the current language I get:
1. 0x4080408
2. 0x4090409
Function return: 0x4090409
(0x4080408 is Greek and 0x4090409 is English)
According to the documentation for ActivateKeyboardLayout, the return value is of type HKL and If the function succeeds, the return value is the previous input locale identifier. Otherwise, it is zero. In my case, the function clearly runs with no errors since it returns the input locale identifier for English witch was the language before the hypothetical change. The language although does not change. I get similar results if I start from greek and try to change to English.
I have tried different values in the flag parameter with no luck. It is always the same thing. I have also tried using the LoadKeyboardLayoutA as follows:
#include <iostream>
#include <windows.h>
int main(){
LPCSTR language_select = "00000408"; // Code for greek
std::cout << LoadKeyboardLayoutA(language_select, KLF_ACTIVATE);
return 0;
}
When running the above code with English as the current language I get:
0x4080408
According to the documentation for LoadKeyboardLayoutA, If the function succeeds, the return type is HKL and the return value is the input locale identifier corresponding to the name specified in the function's parameter (language_select). So this seems to run ok as well but no luck with language change. I also tried with language_select = "00000809" (UK English) and the result I got was Uk English was just added to the list of languages as I did not have it installed.
Finally, I tried calling the ActivateKeyboardLayout with LoadKeyboardLayoutA ad the HKL parameter as follows
#include <iostream>
#include <windows.h>
int main() {
LPCSTR language_select = "00000408"; // Code for greek
std::cout << ActivateKeyboardLayout(LoadKeyboardLayoutA(language_select, KLF_ACTIVATE), KLF_SETFORPROCESS);
return 0;
}
When running the above code with English as the current language I get:
0x4080408
Which again seems normal but there is no chance in the language. I am running this on Windows 10 20H2 OS Build 19042.685 and I am using CLion as an IDE (I don't think it matters but just in case anyone needs the info). What am I doing wrong?
The very first sentence of the ActivateKeyboardLayout function documentation states: "Sets the input locale identifier (formerly called the keyboard layout handle) for the calling thread or the current process.". Since you never read input in your program, you don't observe its effect. It does not change the keyboard layout of the system.
On Windows, each thread has its own keyboard layout. To change the keyboard layout for a specific window, you need to send the WM_INPUTLANGCHANGEREQUEST message to it:
SendMessageW(<windowHandle>, WM_INPUTLANGCHANGEREQUEST, 0, LoadKeyboardLayoutW(language_select, KLF_ACTIVATE));

I want to print in Hebrew (from right to left) to the console

Unlike English and Latin languages, Hebrew - in it's awesomeness, is written right to left. I wan't to get this message across to the computer realm.
I understand I have to use unicode/wchar for the actual string.
I understand I have to set the console to support unicode/wchar.
I understand I have to tell the console to use a supported font.
So I run this code:
#include "stdafx.h" // MS Visual Studio precompiled header file
#include <fcntl.h> // for _setmode
#include <io.h> // for _setmode
#include <windows.h> // for SetCurrentConsoleFontEx
int main()
{
// use unicode/wchar as the actual string.
wchar_t *hebrewString = L"עברית";
// set the console to support unicode/wchar.
_setmode(_fileno(stdout), _O_U16TEXT);
// tell the console to use a supported font.
CONSOLE_FONT_INFOEX info = { 0 };
info.cbSize = sizeof(info);
info.dwFontSize.Y = 20;
wcscpy_s(info.FaceName, L"Courier New");
SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), NULL, &info);
// print
wprintf(L"%s", hebrewString);
// wait for input, so that console won't disappear immediately
getchar();
// return
return 0;
}
This isn't bad, but the actual print is in reverse:
Is there a way to properly configure it so that it will print in the right order, or do I have to manually flip the string before passing it to the console?

GetComputerName() not displaying Unicode correctly in Windows console

I'm relatively new to WinAPI programming in C++. I'm trying to write a program that will obtain the system hostname using GetComputerName(). Ideally, I want the code to be able to work on English and non-English systems. Below is the code that I'm using:
int main()
{
wstring hostname;
wchar_t nbtName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD length = MAX_COMPUTERNAME_LENGTH + 1;
GetComputerName(nbtName, &length);
hostname = nbtName;
wcout << hostname << endl;
return 0;
}
The code works fine on my English Windows 7 system, but the code doesn't seem to display properly on my German Windows 7 system (which uses German characters for the hostname). I thought that wstring and wchar_t could handle these special characters. Here's what's displayed on my German Windows 7 system.
COMPUTER-Í─▄▀
Am I overlooking something stupid? Thanks!
Use _setmode(_fileno(stdout), _O_U16TEXT) to show Unicode in console window:
#include <iostream>
#include <string>
#include <io.h> //for _setmode
#include <fcntl.h> //for _O_U16TEXT
int main()
{
_setmode(_fileno(stdout), _O_U16TEXT);
std::wcout << L"ελληνικά\n";
return 0;
}
Or use MessageBoxW(0, hostname.c_str(), 0, 0) or OutputDebugStringW to see Unicode text displayed correctly:
this function has two versions GetComputerNameW for unicode and GetComputerNameA for ANSI. if UNICODE is defined in your environment the the first one will be called. So either make sure UNICODE is defined or try to call the GetComputerNameW directly.
Windows Console output was the culprit. The Unicode characters display correctly in other non-console output. Thanks everyone!

Change Windows 7 Wallpaper in C++

I saw someone at school who had a program that was supposed to change the background, and log you out (so the change would take effect) but it only worked on his computer, and he "lost" the source code.
I have been looking online for a while for code that would do that, so I could experiment with it.
I found this code (C++)
#include <windows.h>
int main()
{
SystemParametersInfo( SPI_SETDESKWALLPAPER, 0, (PVOID)"image.jpg", SPIF_UPDATEINIFILE );
}
which sort of worked..
It worked twice with an image that was located in the same folder, and I tested two images, and after the second one it just stopped working.
I can't for the life of me figure out why it stopped working (I have tried multiple file extensions, so I know that isn't the issue).
I am working in Dev-C++, if that makes a difference to anyone.
Also, I would like to be able to modify the code to use a url instead of a local image...would that be possible?
Thanks!
Edit: If I change image.jpg to image.bmp it changes every time..But that means that it would only work with *.bmp? I had it working with a jpeg before.
#include <windows.h>
int main()
{
int i;
for(i=0;;i++)
{
Sleep(800);
if(i%2==0)
{
const wchar_t *filenm = L"C:\\Pictures\\image1.jpg"; //ADDRESS of first image
bool isWallSet=SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0,(void*)filenm,SPIF_UPDATEINIFILE);
}
else
{
const wchar_t *filenm = L"C:\\Pictures\\image2.jpg"; //ADDRESS of second image
bool isWallSet=SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0,(void*)filenm,SPIF_UPDATEINIFILE);
}
}
return 0;
}

Running a C++ Console Program in full screen

How to run a C++ Console Program in full screen ? , using VS2008
Just tested this with cl fullscreen.cpp :
#include <iostream>
#include <windows.h>
#pragma comment(lib, "user32")
int main()
{
::SendMessage(::GetConsoleWindow(), WM_SYSKEYDOWN, VK_RETURN, 0x20000000);
std::cout << "Hello world from full screen app!" << std::endl;
std::cin.get();
}
Unfortunatelly it had duplicated the text on the second monitor :)
try:
#include <iostream>
using namespace std;
int main(){
system("mode 650");
system("pause");
return 0;
}
#include <windows.h>
SetConsoleDisplayMode(GetStdHandle(STD_OUTPUT_HANDLE),CONSOLE_FULLSCREEN_MODE,0);
There are not a lot of video adapters around these days that still support this. Run cmd.exe and press Alt+Enter. If you get a message box that says "This system does not support fullscreen mode" then you're done. If it does switch to full screen then you can use SetConsoleDisplayMode() in your main() function. Of course, you don't know what your customer's machine is like, best not to pursue this.
That's what I'm using:
system("mode con COLS=700");
ShowWindow(GetConsoleWindow(),SW_MAXIMIZE);
SendMessage(GetConsoleWindow(),WM_SYSKEYDOWN,VK_RETURN,0x20000000);
It removes the scrollbar :D
For full screen windowed mode: ShowWindow(GetConsoleWindow(), SW_MAXIMIZE);
Just a workaround: You could use some sort of earlier DOS video modi, for example...
asm
{
mov ax, 13h
push bp
int 10h
pop bp
}
...to have a resolution of 320x200 pixels.
But I'm not sure if this would work for a windows application... Probably not!
Just add this line (anywhere) before your output,
system("mode 650");
Such as,
#include<bits/stdc++.h>
using namespace std;
int main(){
system("mode 650");
cout<<"Hey, this words are shown in full screen console! "<<endl;
return 0;
}