2018년 2월 26일 월요일

MFC에서 CString 문자열을 cout을 통해서 콘솔 창에 출력하는 방법





MFC에서 CString 문자열을 cout을 통해서 콘솔 창에 출력하는 방법

간단한 이야기 같으나 멋모르고 달려들다간 간단하지 않다는 걸 깨닫게 된다는게 문제.

CString msg = _T("");
msg += "::_TrackMouseEvent()가 WM_MOUSELEAVE 메시지를 발생 시켰군";
msg += "\n현재의 클라이언트 뷰의 자식 윈도우의 영역을 빠져~~~ 나갈 때~~ 발생시키는 메시지이다.";

//wcout << (const wchar_t*)msg << endl; //이건 띄워쓰기 뒷 부분은 안 나옴
cout << (CString)msg << endl;

위의 코드를 실행하면 cout을 출력하는 부분에서 msg에 대한 주소 값만 달랑 출력하고 끝난다.
0078F488

wcout << (const wchar_t*)msg << endl 
이 방법을 사용해 보면 문자열 내용의 첫 번째 띄워쓰기 뒷 부분은 또 나오질 않는다.

해법은 
프로젝트명 - 마우스 우 클릭 - Properties - Configuration Property -
General - Character set을 Multi-Byte character set으로 설정해 줘야 가능하다.

이렇게 설정하고 나면 cout 대신에 printf()를 이용해도 된다.
참고로 printf()와 cout은 전자가 속도에서 훨씬 빠르다는 것.

printf("%s", msg);  //가능

2018년 2월 21일 수요일

MFC에서 두 개의 문자열 합치기





MFC에서 두 개의 문자열 합치기

자바, C#, python 등의 언어들에서 2개의 문자열을 합치는 것은 간단하고 고민할 필요가 없는 작업이다.
그러나 MFC에서는 자바와 같은 언어들에서 하던 방법으로는 안통한다.
편리한 언어들에 비해서는 좀 불편하긴 하지만 다음과 같은 방법을 사용해서 처리할 수 있다.

CString msg1, msg2, msg3;

msg1 = "여기는 메시지 맵과 메시지 핸들러 함수를 연결하는 방식이 아닌 Win32방식으로 처리해 봄";
msg2 = "\n여기서 이렇게 처리를 해도 메시지 맵과 연결된 메시지 핸들러 함수도 동일하게 처리가 된다.";
msg3 = msg1 + msg2;

MessageBox(msg3);

2018년 2월 19일 월요일

Visual Studio 2010의 Dark color theme 적용하기





Visual Studio 2010의 Dark color theme 적용하기

Visual Studio 2017의 경우는 코드 편집창을 Dark로 변경하는 일이 아주 쉬우나 Visual Studi 2010의 경우는 해당 기능이 제공되지 않는 것 같다.
그렇다고 강렬한 흰색의 압박에 대해 소중한 눈을 방치해 둘수도 없는 노릇이기에 방법을 정리해 본다.

먼저 아래 사이트에서 자신이 원하는 셋팅 파일을 다운로드 받는다.


필자의 경우는 아래 두 개를 보통 사용한다.
vs2017.vssettings
wekeroad-ink.vssettings

위의 환경 설정 파일을 다운로드 받았다면 

도구(Tools) - 설정 가져오기 및 내보내기(Import and Settings) - No, just import new settings, overwriting my current settings 항목 선태 - Browser 버튼 클릭하여 저장된 *.vssettings 파일 가져오기 - Finish






이 후에 글자 크기가 너무 작다면 
도구(Tools) - Options - Environment - Fonts and Colors에서 원하는 크기로 조정하면 된다.





2018년 2월 13일 화요일

동일 PC의 Windows에서 동일 PC에 설치된 Vitrualbox의 Ubuntu 간에 ping이 안될때





동일 PC의 Windows에서 동일 PC에 설치된 Vitrualbox의 Ubuntu 간에 ping이 안될때

※ 전제조건 : 동일 Windows PC상에 Virtualbox가 설치되어 있다고 가정한다.

소켓통신 프로그램을 개발하거나 이더넷 통신... 등등을 개발하다보면 실제 장비와 하기 전에 테스트 차원에서 Virtualbox의 리눅스와 PC간에 통신 프로그램을 개발하는 경우들이 있다.
이때 통신이 정상적인 상태인지를 체크하기 위해 보통은 ping으로 테스트하는 경우가 있다.

아래와 같이 리눅스의 터미널 창에서 PC쪽으로 ping을 날리거나 반대로 PC의 DOS창(커맨더 창)에서 Virtualbox 쪽으로 ping을 날림을 통해서 네트워크 연결 상태를 체크하게 된다.

ping 192.168.211.105

이러한 상황에서 
① 양방향 모두 ping 전송 실패하거나
② PC에서 Virtualbox 쪽으로는 가능하나 그 반대는 안되는 경우
에 대해서 살펴본다.

다른 네트워크 설정 상태가 정상임에도 위 ①의 경우가 발생한다면 우선적으로 Virtualbox의 네트워크 설정 상태를 NAT에서 브릿지 어댑터로 변경해 주어야 한다.
아래 그림과 같이 설정 - 네트워크 - 어댑터1 - 다음에 연결 항목에 있는 NAT를 브릿지 어댑터로 변경한 후 Virtualbox를 재시작한다.


위 ②번의 경우는 아마도 리눅스(여기서는 Ubuntu)의 네트워크 환경 설정 중에서 gateway를 잘못 설정했을 경우에 발생하는 현상이다. 그러나 네트워크의 경우는 워낙 다양한 변수들이 있기에 항상 정답이 될수는 없다.
이 경우 gateway를 올바로 설정하기 위해서는 우선 gateway의 ip 주소를 알아야 한다.
PC의 DOS창을 열어서 ipconfig 명령을 실행하면 아래와 같은 정보를 얻었다면 여기서 "기본 게이트웨이"에 있는 ip를 Ubuntu의 gateway로 설정해 주면 된다.

   연결별 DNS 접미사. . . . :
   링크-로컬 IPv6 주소 . . . . : fe80::84aa:fa63:4a5f:23a2%12
   IPv4 주소 . . . . . . . . . : 192.168.219.186
   서브넷 마스크 . . . . . . . : 255.255.255.0
   기본 게이트웨이 . . . . . . : 192.168.219.1

/etc/network/ 디렉토리 아래에 interfaces라는 파일을 열어서
아래 예시와 같이 gateway의 값을 지정한 후 파일을 저장한다.

auto enp0s3
iface enp0s3 inet static
address 192.168.219.115
netmask 255.255.255.0
gateway 192.168.219.1
dns-nameserver 8.8.8.8 8.8.4.4

이후 다음 명령어로 네트워크 장비를 재시작한다.

ip addr flush enp0s3 && /etc/init.d/networking restart





2018년 2월 6일 화요일

python에서 리눅스 shell command를 이용하여 특정 프로그램의 실행 여부 파악하기





python에서 리눅스 shell command를 이용하여 특정 프로그램의 실행 여부 파악하기

리눅스에서 특정 프로그램의 실행 여부를 파악할 때 터미널 창에서 ps 명령어를 이용해서 대개는 확인하게 된다. SocServer라는 이름을 가진 프로그램이 현재 실행중인지 파악할려면 아래와 같이 한다.

ps -elf | grep SocServer*

이렇게 되면 다음과 같은 정보가 보인다면 해당 프로그램은 실행 중이라는 뜻이다.

0 S root     14851  1812  0  80   0 -  8931 inet_c 16:53 pts/18   00:00:00 python /home/joe/PyCharmProj/SocServer.py

여기서 4번째 column의 값 14851이 SocServer.py의 실행 process id이다. 즉 특정 프로그램의 process가 존재하는지를 통해서 해당 프로그램의 실행 여부를 파악할수 있는 것이다.

이 프로그램의 실행을 강제 종료 시킬려면 다음과 같이 하게 될 것이다.

kill -9 14851

위의 기능과 같은 기능을 하되 보다 단순한 정보를 보여주는 shell command가 있는데 pgrep이다.

pgrep -lf SocServer*

를 하면 다음과 같은 보다 간단한 정보를 나타내준다. 

14851 python

이렇게 간단한 정보를 활용하면 파이썬 상에서 코딩하기가 보다 수월해 진다.
아래는 파이썬에서의 특정 프로그램 실행 여부를 확인하는 코드이다.
이를 위해서는 os와 subprocess 파이썬 모듈을 import 시켜야 한다.


import os
import subprocess

# 이미 실행 중인 process가 있으면 다시 실행되지 않도록 하기 위해
# 실행되는 process가 없으면 0을 반환, 있으면 1을 반환
socSrvProc = subprocess.check_output("pgrep -lf SocServer* | wc -l", shell=True)
print 'socSrvProc : ', socSrvProc

if int(socSrvProc) == 0 :  # SocServer.py가 기존 돌아가고 있는 것이 없으면
    # PC의 C# .DLL library와 소켓 통신을 위한 별도의 프로그램.
    # SocServer.py가 서버 역할 C# .DLL library가 client 역할
    os.system("python /home/joe/PyCharmProj/SocServer.py &")

    print 'SocServer.py를 실행했습니다. 서버 소켓 준비됨'
else :
    print 'SocServer는 이미 실행 중입니다.'

2018년 2월 5일 월요일

python에서 리눅스 쉘 명령어(shell command)를 이용하여 자기 IP 알아내기





python에서 리눅스 쉘 명령어(shell command)를 이용하여 자기 IP 알아내기

소켓 통신 등의 경우 특히 서버 역할을 하는 경우 자기 IP를 스스로 알아내는 코드기 필요하다.
검색해 보면 파이썬에서 이를 알아내는 코드가 소개되어 있는데 다음과 같이

socket.gethostbyname(socket.gethostname())
socket.gethostbyaddr(socket.gethostname())
socket.gethostbyname_ex(socket.gethostname())

127.0.0.1인 loop back IP 값만 반환해 준다.
리눅스의 경우는 파이썬에서 shell command를 적절히 사용하면 여러모로 간한하게 문제를 해결할수 있다.

우선 socket과 subprocess 모듈을 import해야 한다.

import socket
import subprocess

그리고 리눅스 shell command중에서 IP를 확인하는 명령어들이 몇가지 있으나 단지 IP 정보만이 아닌 여러가지 부가적인 정보를 같이 보여주기 때문에 사용하기 용이하지 않다.
대표적으로 ifconfig같은 경우 아래와 같은 정보를 보여준다.

enp0s3    Link encap:Ethernet  HWaddr 08:00:27:ff:a4:58  
          inet addr:192.168.0.150  Bcast:192.168.0.255  Mask:255.255.255.0
          inet6 addr: fe80::c33f:ad86:8225:3597/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:62078 errors:0 dropped:0 overruns:0 frame:0
          TX packets:56852 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:17715562 (17.7 MB)  TX bytes:44145423 (44.1 MB)

lo        Link encap:Local Loopback  
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:65536  Metric:1
          RX packets:108 errors:0 dropped:0 overruns:0 frame:0
          TX packets:108 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000 
          RX bytes:14178 (14.1 KB)  TX bytes:14178 (14.1 KB)

우리가 필요로하는 것은 단지 자신의 IP만 알면 되는데 이 경우 사용할수 있는 명령어가 hostname이라는 shell command이다.

hostname -I를 실행하면 192.168.0.150과 같은 자신의 IP를 알아낼수 있다.
아래는 코드조각이다.

import socket
import subprocess

myIP = subprocess.check_output("hostname -I", shell=True)
print 'My IP : ', myIP

2018년 2월 4일 일요일

python Tkinter GUI 프로그램에서 lambda를 이용한 버튼 이벤트 처리





python Tkinter GUI 프로그램에서 lambda를 이용한 버튼 이벤트 처리

코드에서 막바로 lambda를 이용한 버튼 클릭 이벤트에 대해서 살펴보자.
아래는 코드이다.
프로그램 실행하면 다음과 같은 윈도우 창이 뜨게 된다.



#-*- coding:utf-8 -*-

# 파이썬 GUI용 툴킷 Tkinter를 import
from Tkinter import *

# Tkinter 윈도우 객체 생성
root = Tk()

# (가로 x 세로 + x위치좌표 + y위치좌표)
root.geometry("500x300+300+200")

def callback(number):
    print "Button-", number

print 'b1'
# btn1 버튼 클릭시 실행할 메소드는 callback()이고
# 이 메소드로 넘길 paramter 값은 111이다.
# 따라서 btn1 버튼 클릭시 아래 내용 출력된다.
# Button- 111
btn1 = Button(text="One", command=lambda: callback(111))
btn1.configure(font=("Consolas", 15), width=20)
btn1.pack(pady=7)

print 'b2'
btn2 = Button(text="Two", command=lambda: callback(222))
btn2.configure(font=("Consolas", 15), width=20)
btn2.pack(pady=7)

print 'b3'
btn3 = Button(text="Three", command=lambda: callback(333))
btn3.configure(font=("Consolas", 15), width=20)
btn3.pack(pady=7)

# Tkinter 윈도우 화면에 표시
root.mainloop()