Windows 10의 메모장, 아래아 한글, 워드 패드... 응용 프로그램들의 배경 색이 강렬한 흰색으로 고정되어 이것을 변경하기가 여간 힘든게 아니다. 이전 버전의 Windows들에서 쉽게 변경되던 것들이 버전이 올라가면서 점점 변경하기 어렵게 되어 버렸다.

레지스트리의 값을 변경하는 방법도 있으나(자세한 내용은 여기를 참조) '최대 절전 모드' 등으로 들어갔다가 나오면 레지스트리 변경된 값이 적용이 안되는 문제가 있어 오늘은 일종의 꼼수이지만 이 문제를 보다 간편하게 이용할수 있는 방법을 정리해 보고자 한다.

핵심은 테마(Theme)의 값을 변경함으로 통해서 소기의 목적을 달성코자 한다. 

아래 경로로 가보면 다음과 같은 테마 파일들이 있다.


C:\Windows\Resources\Themes


aero             [DIR] 2017-08-18 00:39:08 ____ 

theme2.theme     2,306 2017-03-19 05:59:08 a___ 

theme1.theme     2,250 2017-03-19 05:59:08 a___ 

aero.theme       1,898 2017-03-19 05:58:27 a___ 

Samsung.theme    1,846 2015-09-30 17:01:58 a___ 


윈도우의 배경색, 바탕화면 배경 이미지, 마우스 관련 등등에 대한 정보를 담고 있고 그런 내용을 결정하는 파일인 테마(Theme)파일들이다.


우리가 정말 간절히 원하는 것은 메모장이나 아래아 한글, 워드패드... 등등의 강렬한 흰색 배경색을 우리가 원하는 색상으로 변경하고자 하는 것이다.

이 문제를 regedit을 이용해서 레지스트리 값을 변경하는 방법으로는 최초 부팅시에는 해당 배경 색이 적용이 되나 '최대 절전 모드'에 들어갔다가 나오면 배경 색상이 원상복구되어 강렬한 흰색이 눈을 자극하는 불쾌하기 짝이 없는 상황에 다시 봉착하게 된다.


이 문제를 해결하는 그래도 대안이 테마의 정보를 담고 있는 파일에 우리가 원하는 색상 정보를 추가하는 것이다.

아래는 aero.theme을 메모장으로 열었을 때의 정보이다.


; Copyright ?Microsoft Corp.


[Theme]

; Windows - IDS_THEME_DISPLAYNAME_AERO

DisplayName=@%SystemRoot%\System32\themeui.dll,-2013

SetLogonBackground=0


; Computer - SHIDI_SERVER

[CLSID\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\DefaultIcon]

DefaultValue=%SystemRoot%\System32\imageres.dll,-109


; UsersFiles - SHIDI_USERFILES

[CLSID\{59031A47-3F72-44A7-89C5-5595FE6B30EE}\DefaultIcon]

DefaultValue=%SystemRoot%\System32\imageres.dll,-123


; Network - SHIDI_MYNETWORK

[CLSID\{F02C1A0D-BE21-4350-88B0-7367FC96EF3C}\DefaultIcon]

DefaultValue=%SystemRoot%\System32\imageres.dll,-25


; Recycle Bin - SHIDI_RECYCLERFULL SHIDI_RECYCLER

[CLSID\{645FF040-5081-101B-9F08-00AA002F954E}\DefaultIcon]

Full=%SystemRoot%\System32\imageres.dll,-54

Empty=%SystemRoot%\System32\imageres.dll,-55


[Control Panel\Cursors]

AppStarting=%SystemRoot%\cursors\aero_working.ani

Arrow=%SystemRoot%\cursors\aero_arrow.cur

Crosshair=

Hand=%SystemRoot%\cursors\aero_link.cur

Help=%SystemRoot%\cursors\aero_helpsel.cur

IBeam=

No=%SystemRoot%\cursors\aero_unavail.cur

NWPen=%SystemRoot%\cursors\aero_pen.cur

SizeAll=%SystemRoot%\cursors\aero_move.cur

SizeNESW=%SystemRoot%\cursors\aero_nesw.cur

SizeNS=%SystemRoot%\cursors\aero_ns.cur

SizeNWSE=%SystemRoot%\cursors\aero_nwse.cur

SizeWE=%SystemRoot%\cursors\aero_ew.cur

UpArrow=%SystemRoot%\cursors\aero_up.cur

Wait=%SystemRoot%\cursors\aero_busy.ani

DefaultValue=Windows Aero

DefaultValue.MUI=@main.cpl,-1020


[Control Panel\Desktop]

Wallpaper=%SystemRoot%\web\wallpaper\Windows\img0.jpg

TileWallpaper=0

WallpaperStyle=10

Pattern=


[VisualStyles]

Path=%ResourceDir%\Themes\Aero\Aero.msstyles

ColorStyle=NormalColor

Size=NormalSize

AutoColorization=0

ColorizationColor=0XC40078D7


[boot]

SCRNSAVE.EXE=


[MasterThemeSelector]

MTSM=RJSPBS


[Sounds]

; IDS_SCHEME_DEFAULT

SchemeName=@%SystemRoot%\System32\mmres.dll,-800


이 테마 파일을 그대로 복사해서 배경색으로 보다 편리하게 변경해서 사용하고자 한다.

변경 절차이다.


1. 도스창을 관리자 권한으로 연다.


2. copy aero.theme joe.theme (joe.theme는 변경하기 원하는 테마 파일의 이름으로 임의로 지정하면 된다)


3. notepad(메모장)을 관리자 권한으로 열어 joe.theme를 연다.


4. 아래 내용을 [Control Panel\Desktop] 항목 위에 추가한 후 저장한다. 209 224 224로 되어 있는 색상 값은 원하는 색상 값으로 작성하면 된다.


[Control Panel\Colors]

Window=209 224 224


색상 변경 값은 Red(209), Green(224), Blue(224)로 설정된 색상이다. 

색상 변경 색은 다음 사이트에서 본인이 원하는 색상 값을 확인할수 있다.


https://www.w3schools.com/colors/colors_picker.asp


5. 파일 탐색기를 열어서 joe.theme에 대한 바로가기를 만든다. 만드는 방법은 joe.theme에 대해 마우스 우측 클릭한 후 팝업메뉴에서 바로가기를 만들면 바탕화면에 바로가기가 만들어진다.


6. 컴퓨터를 부팅 후 joe.theme를 클릭하면 테마관련 창이 뜨는데 그냥 닫으면 그 때 이후부터는 변경된 색상이 모든 프로그램의 배경 색상으로 나타나서 우리의 눈을 편안하게 해 준다.


7. 나쁜 Microsoft 같으니라고~


8. joe.theme가 반드시 C:\Windows\Resources\Themes 이 경로에 위치해야 할 필요는 없다. 편한 곳에 복사해 두었다가 필요할 때 실행하면 된다. 왜냐하면 C:\Windows\Resources\Themes 이 경로에서는 이 파일을 편집하는 것이 관리자 권한이 아니면 안되기 때문에 다른 폴더에 복사해 둔 경우는 색상 변경시 메모장으로 열어서 쉽게 변경된 내용을 저장할수 있기 때문에 다른 경로에 복사해 두면 오히려 더 편리하다. 


가상 포트를 만들어 Serial 통신 기능을 구현해보고자 한다.

특정 장비와 Serial 통신을 하고자 한다면 해당 장비가 제공하는 통신 프로토콜을 파악해야 하는데 이 프로토콜을 파악한 것이 맞는지 어떤지 처음에는 확인이 되지 않을수가 있다.


따라서 가상 포트를 만드는 이유는 실제 장비와 Serial 통신을 함에 있어서 정상적으로 데이터 송/수신이 되는지을 확인한다거나 할 때 유용하기 때문에 가상 포트를 통해서 구현해 보고자 한다.

미션 수행은 다음과 같은 단계로 처리가 된다.


-. VSPE(Virtual Serial Port Emulator)를 이용한 가상 포트 만듦

-. Hyper Terminal을 이용해 VSPE가 만든 가상 포트에 연결 해 둠

-. C#에서 VSPE가 만든 가상 포트를 열어 해당 포트에 연결되어 있는 하이퍼터미널과 통신


먼저 VSPE를 설치한다. 

SetupVSPE.zip


그리고 가상 포트에 연결될 장비로 여기서는 하이퍼터미널을 사용할 것이다.

역시 하이퍼 터미널을 설치한다.

HyperTerminal_Kor.zip


VSPE를 실행해 보자. 64bit를 사용해 달라는 창이 뜨면 '아니요'를 선택한다.



위의 적색 박스안의 아이콘을 클릭해서 가상 포트를 만들어 보자.



위의 창에서 Device Type을 Connector 상태에서 '다음' 버튼 클릭한다.




위의 창에서 이제 원하는 포트를 선택해서 가상 포트를 하나 만든다. 여기서는 COM9을 선택했다.

이렇게 만들어진 가상 포트에 하이퍼터미널을 연결해서 C# 응용프로그램에서 COM9에 연결된 장비(하이퍼터미널)과 시리얼 통신을 할 것이다.

이제 하이퍼터미널을 실행한다.



새 연결 이름을 포트의 이름과 같이 명명했다. 확인 버튼을 클릭한다.



위의 창에서 '연결에 사용할 모뎀' 항목에 앞에서 만들었던 가상포트(COM9)를 선택한 후 확인 버튼 클릭




포트의 속성 정보를 설정한다. 여기서 속도(비트/초(B)와 '흐름 제어'를 위와 같이 설정한 후 확인을 클릭한다.



파일 - 속성 메뉴를 클릭해서 뜨는 창에서 '설정' 탭을 클릭한다. 그리고 적색 박스 부분의 'ASCII 설정' 버튼을 클릭한다.



ASCII 설정 창이 뜨면 위와 같이 항목들을 체크한다.

이렇게 하는 이유는 하이퍼터미널에서 송/수신 데이터를 화면에 보이도록 하기 위함이다.

이제 통신을 위한 준비 작업은 끝났다.


C#에서 만든 시리얼 통신 프로그램을 실행해서 통신을 해보자.



앞에서 만든 가상 포트에 연결된 하이퍼터미널로 위와 같은 데이터를 전송해 보았다.




이렇게 시리얼 통신이 잘 되고 있다.


아래는 시리얼 통신용 C# 쪽의 소스 코드이다.


using System;

using System.Collections.Generic;

using System.ComponentModel;

using System.Data;

using System.Drawing;

using System.IO.Ports;

using System.Linq;

using System.Text;

using System.Threading.Tasks;

using System.Windows.Forms;


namespace ExSerialCom

{

    public partial class Form1 : Form

    {


        private SerialPort sPort;

        private string portName = "Select Port";

        private string rxText = "";


        public Form1()

        {

            InitializeComponent();


            string[] ptNum = SerialPort.GetPortNames();


            for (int i=0; i<ptNum.Length; i++)

            {

                cmbPort.Items.Add(ptNum[i]);

            }

        }


        private void btnOpen_Click(object sender, EventArgs e)

        {

            sPort = new SerialPort();


            if(portName.Contains("Select"))

            {

                MessageBox.Show("포트를 선택해 주세요");

                return;

            }


            if(sPort.IsOpen)

            {

                MessageBox.Show("포트가 이미 열려있습니다");

                return;

            }


            sPort.PortName = portName;

            sPort.BaudRate = 9600;

            sPort.DataBits = 8;

            sPort.Parity = Parity.None;

            sPort.DataReceived += Port_DataReceived;

            //sPort.ErrorReceived += new SrialErrorReceivedEventHandler(serialPort_ErrorReceived);


            sPort.Open();

            if(sPort.IsOpen == true)

            {

                MessageBox.Show("포트 열기 성공");

            } else

            {

                MessageBox.Show("포트 열기 실패");

            }


        }


        private void btnClose_Click(object sender, EventArgs e)

        {

            if(sPort != null && sPort.IsOpen)

            {

                sPort.Close();

            }

        }


        private void btnSend_Click(object sender, EventArgs e)

        {

            if(richTextBox1.Text.Length > 0)

            {

                //포트 오픈 여부 체크

                if(sPort == null || sPort.IsOpen == false)

                {

                    MessageBox.Show("포트를 열어 주세요");

                    return;

                } else

                {

                    sPort.Write(richTextBox1.Text);

                }

            }

        }


        private void cmbPort_SelectedIndexChanged(object sender, EventArgs e)

        {

            portName = cmbPort.SelectedItem.ToString();

        }


        private void Port_DataReceived(object sender, SerialDataReceivedEventArgs e)

        {

            rxText = sPort.ReadExisting();

            this.Invoke(new EventHandler(DisplayText));

        }


        private void DisplayText(object sender, EventArgs s)

        {

            richTextBox1.Text += rxText;

        }

    }

}




윈도 10에서 메모장을 열면 백색의 강렬함이 눈을 자극한다. 몹시...

그런데 이걸 바꿀수 있는 기능이 이전 윈도우들에서는 제공이 되었으나 지금은 없는 듯 하다.

발전은 못할망정 이건 뭐...

하는 수 없이 윈도우의 레지스트리 변경을 통해 하는 수 밖에 없다.

근데 이건 조심하지 않으면 땀 나는 경우가 있다.

다음 순서로 진행한다


-. 윈도우 키 + R

-. regedit

-. HKEY_CURRENT_USER

-. Control Panel

-. Colors


우측에 여러 항목들이 나타난다. 이들 중에서 

Window라는 항목에 데이터 값이 255 255 255로 되어 있을 것이다.

이 값을 변경하면 윈도의 창 배경색이 바뀐다. 메모장, 아래아 한글...

255 255 255는 차례대로 Red Green Blue의 색상 값이다.


이 색상 값을 어떻게 변경할지를 참조할 사이트는


https://www.w3schools.com/colors/colors_picker.asp


이곳에서 색상의 값과 색상이 어떤 색인지를 확인해서 값을 변경하면 된다.

데이터 값 변경은 해당 항목(Window)에 마우스 우측 클릭 후 "수정" 메뉴 클릭해서 변경하면 된다.


그 다음 항목으로 Window Text 항목이 있는데 이 항목의 데이터 값은 0 0 0으로 되어 있을 것이다.

이것은 글자 색이 검정색임을 의미한다.


이후 PC를 재 부팅한다.


단 이상의 색상들을 변경함으로 인해 윈도우 다른 프로그램들에서 글자가 안 보이는 현상이 없도록 색상 조합을 잘 해줘야 한다.

미덥지 않으면 기존의 색상 값을 다른 곳에 잘 저장해 둘 필요도 있고 혹은 레지스트리 값을 백업해 둘 필요도 있다.




리눅스에서 터미널을 여러개 띄워놓고 작업을 할 경우 마우스로 드래그해 가면서 창의 크기를 조절해서 화면분할해 가면서 사용해야 하는 불편함이 있다.

이를 보다 간편하게 해결할수 있는 기능이 탭 기능이다.


Ctrl-Shift-T를 하면 현재의 터미널 상에서 새로운 탭(크롬과 같은 웹 브라우저에서 새 탭에서 웹 페이지 여는 것과 같은...)이 생기면서 새로운 터미널 창을 열수 있다.

이렇게 여러개의 탭으로 터미널을 열면 작업하기가 무지 편해 진다.




탭 간의 이동은

 -. Alt + 1/2/3... 으로 각 탭으로 이동하는 방식과

 -. Ctrl + PageUp/PageDown으로 각 탭으로 이동하는 방식이 있다.

위의 방식이 보다 쉬운 방식이리라...


현재 탭 닫기는

Ctrl + Shift + w





본 프로그램은 n명의 학생 각각이 m개의 과목을 수강할 경우에 대한 

2차원 배열을 선언하는 형태인데 학생 수가 고정되어 있지 않고 가변이고

각 학생의 수강 과목도 고정되어 있지 않고 각각 상이하다고 할 때의 

상황이다. 이때 가장 적합한 2차원 배열의 형태가 "2차원 포인터(포인터의 포인터)"

형태로 선언하는 것에 대한 예제 코드이다.


#include <iostream>

#include <malloc.h>


using namespace std;


void main()

{

//2차원 포인터는 2차원 배열의 형태를 갖는데 

//세로(행, row)도 가변적인 배열, 가로(열, column)도 가변의 크기를 갖는 배열이라는 뜻이다.

int** score;

int studentNum = 0;

int lessonNum = 0;

int allTotalSize = 0;


cout << "학생 수 입력 : ";

cin >> studentNum;


//studentNum 갯수 만큼의 크기를 가진 배열이 선언되는데 이 배열의 각 원소가

//int형 포인터 변수이므로 각 원소가 또 동적 할당으로 임의 크기의 배열의 시작 주소를

//가리키게 되므로 결국 2차원 배열이 되는 것이다.

//즉 studentNum 갯수 만큼의 크기를 가진 int형 포인터 변수가 배열 형태로

//선언되고 그 시작 주소 값을 score에 저장한다.

//통상적으로 이렇게 생성되는 배열을 2차원 배열의 행(row, 가로)의 크기로 본다.

score = new int*[studentNum];

cout << "sizeof(score) : " << sizeof(score) << " byte" << endl;

cout << "_msize(score) : " << _msize(score) << " byte" << endl << endl;


//_msize()함수에 대해: new로 생성된 메모리는 heap 메모리 영역에 생성되고

//heap 메모리 영역은 운영체자가 관리해 주기 때문에 동적 할당된 메모리의 크기를

//알기 위해서는 운영체제의 도움이 필요하다.

//윈도우의 경우 _msize()함수를 통해 알수 있다.

//반면에 sizeof()함수는 포인터 변수 자체의 크기를 반환하는데 포인터 변수는 항상 4byte로 동일하다

//아래의 코드는 score가 가리키는 동적 할당된 메모리 전체의 크기를 반환한다.

//score = new int*[studentNum]으로 할당되었기에 

//studentNum * 4(int형의 크기가 4byte이므로)의 크기를 가진다.

allTotalSize = _msize(score);


//studentNum 갯수 만큼의 배열 각 요소인 int형 포인터 변수 각각에 대해

//동적 메모리 할당을 통해 또 다시 배열을 만든다. 따라서 2차원 배열이 되는 것이다.

//통상적으로 이렇게 생성되는 배열을 2차원 배열의 열(column, 세로)의 크기로 본다.

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

{

cout << (i+1) << "번 학생의 수강 과목 수 : ";

cin >> lessonNum;


score[i] = new int[lessonNum];

allTotalSize += _msize(score[i]);

cout << (i + 1) << "번째 배열의 크기 : " << _msize(score[i]) << " byte" << endl << endl;

}


cout << endl << "2차원 포인터 배열 전체의 크기 : " << allTotalSize << " byte" << endl;


//여기서 성적 입력 및 평균, 총점 처리...


//메모리 해제(동적 할당된 메모리는 사용후 반드 해재해 줘야함!)

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

{

delete[] score[i];

//delete score[i]; //이 경우는 i번째 배열 전체가 아닌 그 배열의 시작 주소만 해제 함

}


delete[] score;


cout << endl << "동적 할당 메모리 해제 완료~" << endl;

}


실행 결과는 다음과 같다.








'C++' 카테고리의 다른 글

C#의 .dll Library를 C++에서 활용하기  (0) 2017.12.08
memcpy()함수를 이용한 문자열 복사 하기  (0) 2017.07.25

몇 가지 리눅스 명령어


1) getconf LONG_BIT

 -. 현재의 리눅스 시스템이 32비트인지 64비트인지 확인

 -. 예) # getconf LONG_BIT


리눅스 상에서 가끔 실행파일을 실행시켜 보면 "cannot execute binary file: Exec 형식 오류"과 같은 에러가 발생할수가 있다. 이건 리눅스가 32비트인데 64비트 실행파일을 실행하고자 할때의 경우에 발생한다.


2) wget

 -. http, https, ftp 프로토콜을 이용하여서 웹에 있는 특정 파일을 다운로드

 -. 예) wget http://www.som.co.kr/qt-opensource-linux-x64-5.8.0.run


리눅스의 웹 브라우저등으로 웹 상의 파일을 다운로드 할수도 있으나 부득이 터미널 창에서 웹의 파일을 다운로드 받아야 할 경우 wget으로 편리하게 다운로드 받을수 있다.


3) apt-cache pkgnames | grep 패키지_이름

 -. 현재의 리눅스에 설치되어 있는 패키지 프로그램을 찾고자 할 때 사용

 -. 예) apt-cache pkgnames | grep wget

        (wget이 설치되어 있는지 확인할수 있다)


4) lpq 

 -. 프린트 큐에 있는 작업의 목록을 보여주는 명령어

 -. 예) lpq

         EPSON-L365-Series is ready

         no entries


5) cat /proc/cpuinfo

-. cpu에 대한 전체적인 정보가 나온다.


6) dpkg --print-architecture

-. Linux Kernel architecture 확인

-. 여기서 나오는 정보는 amd64, arm64, armhf, i386 등의 정보가 나온다.


7) ls -sh

-. 파일 목록을 보여줄때 파일 사이즈를 Kb, Mb의 형식으로 표시(파일이름과 사이즈 정보만 표시됨). 디폴트는 byte단위로 표시됨

-. 여기서 s는 size, h는 human readable형식을 뜻한다.

-. 만일 자세한 정보를 같이 표시할려면 ls -lsh







memcpy()함수를 이용한 문자열 복사 하기


char *name = "홍 길동";


//strlen() : 현재 문자열의 크기 값을 반환

//size_t strlen(const char *_Str)

//따라서 매개인자의 데이터 타입은 char* 형

char *kkk = new char[strlen(name) + 1];


//만일 char *kkk = new char[strlen(name) + 1]의 작업 없이 

//char *kkk;로만 선언후 memcpy(kkk, name, strlen(name))과 같이 하면

//이 경우는 "초기화되지 않은 'kkk' 지역 변수를 사용했습니다."라는 에러 발생.

//이유는 메모리 할당되지 않은 상태에서 memcpy()로 복사하고자 했기 때문이다.


//memcpy() : void *memcpy(void *dest, const void *src, size_t count)

//아래는 name에 있는 문자열을 kkk에 복사를 하되 strlen(name)+1만큼 복사

memcpy(kkk, name, strlen(name));


//printf("kkk : %s\n", kkk);

//cout << "kkk : " << *kkk << endl; //not work

cout << "kkk : " << kkk << endl; //work





네트워크 연결 상태를 체크할 때 가장 손쉬운 방법이 ping을 통해서 테스트해 보는 방식이다.

그런데 윈도우쪽에서 다른 쪽으로 ping이 정상적으로 전송되는데 반대로

그 다른 쪽에서 윈도우쪽으로는 ping이 불가능할 때가 있다.

이때 콘솔 창(DOS 창)을 관리자 권한으로 연 후 아래 명령어를 입력하면 해결 끝


netsh advfirewall firewall add rule name="ICMP Allow" protocol=icmpv4:8,any dir=in action=allow


관련된 자세한 정보를 볼려면


netsh advfirewall firewall show rule name="ICMP Allow" dir=in type=dynamic


MFC 개발시 콘솔창(DOS 창)에 로그 출력하기.


MFC 개발시 프로그램 실행의 정보를 콘솔 창에 로그로 출력하기 위해서는 

stdafx.cpp안에 아래 코드를 추가하면 프로그램이 실행될 때 콘솔 창이 뜨고 printf()나 cout으로 출력하는 값이 표시가 된다.


#pragma comment(linker, "/entry:WinMainCRTStartup /subsystem:console")    //semicolon이 없음


TestView.cpp에서 특정 변수의 값을 콘솔창에 출력하고 싶다면


#include <iostream> //cout으로 출력하기 위해


... 중 략 ...


std::cout << "x : " << point.x << std::endl;

printf("결과 : %d\n", point.x);


과 같이 사용하면 된다.





우분투는 최초 설치 후 기본적으로 root 계정으로 접속할수 없다. root 계정은 만들어져 있으나 암호 설정이 되어 있지 않다. 이럴 때 우분투 초기 설치후 root 계정의 비밀번호를 생성해 주면 된다.

방법은 다음과 같이...


$ sudo passwd root

[sudo] password for 현재로그인한사용자: <여기에서 현재 로그인한 사용자의 비번을 입력한다>

새 UNIX 암호 입력 : <여기에 root 비번입력>

새 UNIX 암호 재입력 : <여기에 root 비번 다시 입력>

passwd: 암호를 성공적으로 업데이트했습니다.


$ su

암호: <여기에 root 비번 입력>


root@.... # 


위와 같이 prompt가 #로 바뀌면 root 계정으로 정상적으로 로그인한 것이다.




+ Recent posts