Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > C/C++ программирование > Общие вопросы C/C++
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 15.04.2018, 20:30   #1
Patangaly
 
Регистрация: 15.04.2018
Сообщений: 5
По умолчанию Перевод из Юникода в мультибайтную строку. (Проблема)

Простая программа, которая берёт первый аргумент командной строки и помещает его в буфер обмена, почему-то меняет кодировку строки, пройдя через функцию WideCharToMultiByte. То есть, после того как строку вставляешь в любой текстовый редактор из буфера обмена, если в строке есть кириллица, выдаёт набор бессмысленных символов.
Компилятор MinGW 0.6.2.
Код:

Код:
// clip.cpp

#include <windows.h>
#include <iostream>
#include <cstring>

#define arg_size 512
#define _CP 1251

int WinMain (HINSTANCE hInst, HINSTANCE hPreInst, LPSTR lpCommandLine, int nShow)
{
	int pnArgs;
	WCHAR **lpArrArgs;
	HGLOBAL hgMem;
	wchar_t *lpMem;
	char lpzArg_1[arg_size];
	int cbWide;

	lpArrArgs = CommandLineToArgvW (GetCommandLineW (), &pnArgs);
	if (OpenClipboard (NULL) && pnArgs > 1)
	{
		hgMem = GlobalAlloc (GMEM_MOVEABLE, wcslen (lpArrArgs[1]) + 1);
		if (hgMem)
		{
			lpMem = (wchar_t*) GlobalLock (hgMem);
			EmptyClipboard ();
			cbWide = WideCharToMultiByte (_CP, 0, lpArrArgs[1], -1, NULL, 0, NULL, NULL);
			WideCharToMultiByte (_CP, 0, lpArrArgs[1], cbWide, lpzArg_1, arg_size, NULL, NULL);[/B]
			memcpy (lpMem, lpzArg_1, wcslen (lpArrArgs[1]) + 1);
			SetClipboardData (CF_TEXT, hgMem);
		} else {
			std::cout << "Error memory allocation..." << GetLastError () << std::endl;
		}
		GlobalUnlock (hgMem);
		CloseClipboard ();
		GlobalFree (hgMem);
	} else {
		std::cout << "clip: no params...";
	}
	ExitProcess (0);
}
Все виды кодовых страниц уже были перепробованы, но буфер обмена всегда на кириллицу выдаёт строку не в той кодировке.

Результат:
codepage.jpg

Последний раз редактировалось Patangaly; 15.04.2018 в 20:46.
Patangaly вне форума Ответить с цитированием
Старый 16.04.2018, 20:41   #2
alexzk
Форумчанин
 
Регистрация: 12.04.2017
Сообщений: 889
По умолчанию

У вас сама командная строка обыкновенное ASCII

LPSTR lpCommandLine

https://stackoverflow.com/questions/...n-and-wwinmain


А вообще делайте стандартно функцию main() (как в примере у МС https://msdn.microsoft.com/en-us/lib...(v=vs.85).aspx).

Последний раз редактировалось alexzk; 16.04.2018 в 20:43.
alexzk вне форума Ответить с цитированием
Старый 17.04.2018, 12:52   #3
Patangaly
 
Регистрация: 15.04.2018
Сообщений: 5
По умолчанию

Даже, если использовать main () и брать ANSI-строку из argv[], то в буфере обмена всё равно теряется кириллица.
Patangaly вне форума Ответить с цитированием
Старый 17.04.2018, 20:04   #4
Patangaly
 
Регистрация: 15.04.2018
Сообщений: 5
По умолчанию

На всякий случай отпишусь.
Оказывается, помещая текст в буфер обмена после его очистки, ANSI-строка, особенно, если она содержит символы не латинского алфавита, должна быть локализована. Для этого надо в буфер обмена поместить флаг локализации CF_LOCALE, а потом уже и сам текст.
Код:
// clip.cpp

#include <windows.h>
#include <tchar.h>
#include <iostream>
#include <cstring>

#define arg_size 512
#define _CP CP_ACP

int WinMain (HINSTANCE hInst, HINSTANCE hPreInst, LPSTR lpCommandLine, int nShow)
{
	setlocale (LC_ALL, _T("Russian"));

	int pnArgs;
	LPWSTR *lpArrArgs;
	HGLOBAL hgMem;
	LPVOID lpMem;
	TCHAR lpzArg_1[arg_size];
	int cbWide;

	lpArrArgs = CommandLineToArgvW (GetCommandLineW (), &pnArgs);
	if (OpenClipboard (NULL) && pnArgs > 1)
	{
		cbWide = WideCharToMultiByte (_CP, 0, lpArrArgs[1], -1, NULL, 0, NULL, NULL);
		WideCharToMultiByte (_CP, 0, lpArrArgs[1], cbWide, lpzArg_1, arg_size, NULL, NULL);
		hgMem = GlobalAlloc (GMEM_MOVEABLE, _tcslen (lpzArg_1) + 1);
		if (hgMem)
		{
			if (lpMem = GlobalLock (hgMem))
			{
				memset (lpMem, 0, _tcslen (lpzArg_1));
				memcpy (lpMem, lpzArg_1, _tcslen (lpzArg_1));
				EmptyClipboard ();
				SetClipboardData (CF_LOCALE, lpMem);
				SetClipboardData (CF_TEXT, lpMem);
			} else {
				std::cout << "GlobalLock (): Error memory allocation..." << GetLastError () << std::endl;
			}
		} else {
			std::cout << "GlobalAlloc (): Error memory allocation..." << GetLastError () << std::endl;
		}
		CloseClipboard ();
		GlobalUnlock (hgMem);
		GlobalFree (hgMem);
	} else {
		std::cout << "clip: no arguments...";
	}
	ExitProcess (0);
}

Последний раз редактировалось Patangaly; 17.04.2018 в 20:07.
Patangaly вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Перевод числа в строку Drimetolle Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 8 01.05.2017 03:04
перевод в строку из Double Dimarik Assembler - Ассемблер (FASM, MASM, WASM, NASM, GoASM, Gas, RosAsm, HLA) и не рекомендуем TASM 0 18.09.2011 15:32
Перевод на новую строку Fanyuus Помощь студентам 6 15.05.2011 13:01
Перевод времени в строку noob_11 Общие вопросы C/C++ 2 18.04.2010 21:30
Перевод чисел в строку RedWolf Помощь студентам 6 17.01.2008 00:09