[C++] Uzysk. dost. do schowka. Otw. i zam. zew. programów

Witam,

Jaki jest kod, który pozwoli mi wprowadzać wartości do programu ze schowka, wklejać wynik pracy programu do schowka, wyczyścić schowek oraz do pozostałych czynności na jakie język c++ pozwala?

Chodzi o program konsolowy, bo widziałem w Internecie dla okienkowych kody, ale jeszcze do tego nie doszedłem. Dopiero się uczę podstaw w konsoli.

W C++ nie ma czegoś takiego jak schowek :stuck_out_tongue:

Zapewne chodzi Ci o schowek Windowsowy.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms648709

#include 

#include 

#include 


std::string getClip()

{

	std::string res;

	if(!OpenClipboard(0))

		return res;

	HANDLE hMem = GetClipboardData(CF_OEMTEXT);

	if(!hMem)

	{

		CloseClipboard();

		return res;

	}

	char* p = (char*)GlobalLock(hMem);

	if(!p)

	{

		CloseClipboard();

		return res;

	}

	res = p;

	GlobalUnlock(hMem);

	CloseClipboard();

	return res;

}


bool setClip(const std::string& txt)

{

	HANDLE hMem = GlobalAlloc(GMEM_MOVEABLE, txt.length() + 1);

	if(!hMem)

		return false;

	char* p = (char*)GlobalLock(hMem);

	if(!p)

	{

		GlobalFree(hMem);

		return false;

	}

	for(size_t i = 0; i <= txt.length(); ++i)

		p[i] = txt[i];

	GlobalUnlock(hMem);

	if(!OpenClipboard(0))

	{

		GlobalFree(hMem);

		return false;

	}

	EmptyClipboard();

	SetClipboardData(CF_OEMTEXT, hMem);

	CloseClipboard();

	return true;

}


int main()

{

	std::cout << getClip() << std::endl;

	std::string t;

	std::cin >> t;

	setClip(t);

	return 0;

}

Na MSDN jest napisane, że SetClipboardData nie powiedzie się jeśli do OpenClipboard nie zostanie podane jakieś okno, ale na XP SP3 działa bez okna.

Dzięki za zainteresowanie się tematem :slight_smile:

Chciałbym napisać program, który po wpisaniu 2 wartości - ciągu znaków (ew. to co jest aktualnie w schowku) i mnożniku powielał ciąg znaków (lub ciąg znaków zawartych w schowku).

np.

tekst

5

tekst tekst tekst tekst tekst

Kod podany przez Ciebie wyświetla zawartość schowka windowsowego w oknie konsoli. Rozumiem, że getClip() wsadzić do zmiennej i dać do pętli (sterowaną zmienną, którą wpiszę na początku), a na koniec kopia tego co tam namnożyło kodem do wklejania wyników programu do schowka… Tylko jaki kod…

Angielskiego nie znam na za dobrze, a po tłumaczeniu Google dalej jakoś się w tym gubię…

Jeśli masz zmienną np. std::string tekst; zawierającą początkowy tekst i int ile; zawierającą liczbę ile razy ma zostać powtórzony tekst oraz zmienną std::string wynik na początku pustą, do której ma zostać zapisany powtórzony tekst to

for(int i = 0; i < ile; ++i)

	wynik += tekst;

Teksty w zmiennej wynik będą sklejone, jeśli chcesz mieć poszczególne kopie rozdzielone spacjami to łączysz w ten sposób

for(int i = 0; i < ile; ++i)

	wynik += tekst + ' ';

Ale wtedy będziesz miał na końcu dodatkową spację, aby ją usunąć musisz skrócić napis o 1 znak

wynik.resize(wynik.length() - 1);

To warto się trochę pouczyć :wink: Powinny wystarczyć podstawy gramatyki (w dokumentacji raczej rzadko spotyka się bardziej skomplikowane konstrukcje), podstawowe słownictwo angielskie i trochę słownictwa technicznego :slight_smile:

PS. W kodzie, który podałem w poprzednim poście używałem formatu danych CF_OEMTEXT, czyli tekstu kodowanego OEMową strona kodową, ponieważ konsola standardowo używa takiej strony kodowej (ze względu na kompatybilność konsola używa starych DOSowych stron kodowych). Jest też typ CF_TEXT, który oznacza tekst kodowany stroną używaną przez resztę systemu (podstawowy zestaw ASCII jest identyczny, znaki diakrytyczne mają różne kody). Jest też typ CF_UNICODETEXT, oznaczający tekst kodowany UTF16 (unicode, każdy znak zajmuje 2 bajty i napis kończy się dwoma null-bajtami (“zwykły” tekst jednym), używany przez kernel Windowsa i zalecany dla nowych programów, typy: char->wchar_t, std::string->std:: w string, itp.; więcej info tu i tu).

Hm… Trochę to skomplikowane… Później spróbuję to wykonać…

A tymczasem mam pytanie… Jaki jest kod na uruchamianie i zamykanie programów? W Google szukałem… jest dużo stron, ale mi nie działają te kody - albo są błędy według kompilatora albo podczas działania programu wyskakują mi jakieś wiadomości, a ja ich nie chcę…

Zależy od systemu:

Windows:

link

Linux:

fork + execve

W Windowsie. Hm… Tam coś pisze o WinApi, a ja jestem na etapie programów konsolowych. Będzie działać?

A czemu miałoby nie działać?

Co skomplikowane? :wink:

Uruchamiać możesz np. funkcją system, która wywołuje interpreter poleceń z podanym poleceniem (możesz podawać te same polecenia jak do cmd).

Z WinAPI możesz użyć ShellExecute lub ShellExecuteEx, które służą do wywoływania poleceń powłoki, m.in. umożliwiają odpalanie programów. możesz też bezpośrednio użyć CreateProcess do utworzenia procesu, jak radzi kostek135.

Co do zamykania, to możesz użyć TerminateProcess do ubicia procesu. W przypadku aplikacji okienkowych możesz wysłać WM_CLOSE do głównego okna aplikacji (działa jak wciśnięcie krzyżyka na okienku) lub WM_QUIT do głównego wątku aplikacji, w odpowiedzi wątek powinien się zakończyć.

PS. Trochę off-topic :wink:

To dodam do tematu wątku drugie zagadnienie…

Trochę niefajnie ten temat teraz wygląda, ale cóż… Ograniczenie długości :frowning:

A bo ja jeszcze pętli nie ogarniam do końca, a tu takie zaawansowane… :-o

Myślałem, że to trochę łatwiejsze będzie… Pewnie wrócę do tego jak dojdę do takiego typu funkcji chyba, że przeskoczę lekcje… :lol:

Czyli w moim programiku wpisać kod np.

WM_CLOSE notepad.exe

z nagłówkiem

#include windows.h

:?:

Dodane 16.08.2013 (Pt) 19:37

Tak w ogóle to ja mam problem z odczytywaniem tej strony MSDN… Nie rozumiem… jak by to powiedzieć… Jej układu, zapisu poleceń… Nie mogę się np. doszukać jaki nagłówek jest wymagany do poleceń zawartych na tej stronie.

Ehh… programowanie w c++ nigdy nie było przyjemne zwłaszcza na poziomie systemowym.

Bez jaj… link

Acha… to tam…

No a gdzie jest funkcja z przykładową aplikacją napisana dla WM_CLOSE… Po wklejeniu do programu tej funkcji z nawiasem, w którym jest nazwa procesu, nie działa.

To radzę Ci się douczyć najpierw C++ :wink:

Polecam:

Do większości rzeczy z WinAPI wystarczy

WM_CLOSE to nie funkcja, tylko komunikat do okna.

HWND hWnd = FindWindow(TEXT("Notepad"), NULL);

	if(hWnd)

		PostMessage(hWnd, WM_CLOSE, 0, 0);

“Notepad” to nazwa klasy okna notatnika, nie nazwa programu. Notatnik wyświetli pytanie o to czy zapisać zmiany jeśli coś wpisywałeś (tak jak standardowo po kliknięciu mu X). Zamiast wysyłać WM_CLOSE do okna możesz też wysłać WM_QUIT do wątku

HWND hWnd = FindWindow(TEXT("Notepad"), NULL);

	if(hWnd)

	{

		DWORD dwTID = GetWindowThreadProcessId(hWnd, NULL);

		if(dwTID)

			PostThreadMessage(dwTID, WM_QUIT, 0, 0);

	}

Opcjonalnie możesz brutalnie ubić proces

HWND hWnd = FindWindow(TEXT("Notepad"), NULL);

	if(hWnd)

	{

		DWORD dwPID = 0;

		GetWindowThreadProcessId(hWnd, &dwPID);

		if(dwPID)

		{

			HANDLE hProcess = OpenProcess(PROCESS_TERMINATE, FALSE, dwPID);

			if(hProcess)

			{

				TerminateProcess(hProcess, 0);

				CloseHandle(hProcess);

			}

		}

	}

ID procesu pozyskałem tutaj z okna, ale nie ma różnicy skąd został wzięty, ważne żeby się zgadzał :wink:

Pierwszy argument OpenProcess to żądane uprawnienia, tutaj program prosi o prawo ubicia procesu.

Lepiej byłoby poprosić moda o wydzielenie wątku :wink: