300x250
반응형

 

 

[ 프로그램 UI ]

프린트 버튼을 누르면

 

위와 같이 프린트 다이얼로그가 뜨면서 인쇄할 수 있습니다.

(프린트 다이얼로그가 안뜨게 하는 코드도 첨부)

 

 

[ 주요 메인 코드 ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 
void CPrintTestDlg::OnBnClickedButton1()
{
    CTime t = CTime::GetCurrentTime();
    CString str_time;
 
    int temp_year = (int)(t.GetYear() / 100* 100;
    temp_year = t.GetYear() - temp_year;
 
    str_time.Format(_T("Capture_%02d%02d%02d_%02d%02d%02d.png"), temp_year, t.GetMonth(),
        t.GetDay(), t.GetHour(), t.GetMinute(), t.GetSecond());
    save_path_png_ = GetExecutedPath() + str_time;
 
    //1. 이미지 저장
    Capture(save_path_png_);
 
    //2. 이미지 프린트
    PrintOutImage(save_path_png_);
 
    //3. 파일 삭제
    DeleteFile(save_path_png_);
}
 
cs

버튼을 누르면 현재 시간으로 파일 경로를 만듭니다.  그 이 후

 

1. Capture() : 이미지 캡쳐 및 저장 함수 ( 듀얼 모니터 인식 )

2. PrintOutImage() : 이미지 출력 함수 ( 출력 다이얼로그 ON / OFF 가능)

3. DeleteFile() : 파일 삭제 함수

 

와 같은 순으로 함수가 호출 됩니다.

 

 

[ 나머지 함수 코드 ]

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
 
CString CPrintTestDlg::GetExecutedPath()
{
    //실행파일 경로 구하는 함수
    CString strResult;
    CString strPath;
 
    if (GetModuleFileName(nullptr, strPath.GetBuffer(_MAX_PATH + 1), MAX_PATH) != FALSE)
    {
        strPath.ReleaseBuffer();
        strResult = strPath.Left(strPath.ReverseFind('\\'+ 1);
    }
 
    return strResult;
}
 
 
CPoint CPrintTestDlg::GetPopupOffset()
{
    CPoint point;
 
    CRect rect;
    this->GetWindowRect(rect); // 메인 다이얼로그 Rect를 받아야 함
    point.x = rect.left;
    point.y = rect.top;
 
    return point;
}
 
 
void CPrintTestDlg::Capture(CString file_name)
{
    CRect rect;
    GetClientRect(rect);
 
    CWnd* pWndDesktop = GetDesktopWindow();
    CWindowDC ScrDC(pWndDesktop);
 
 
    int sx = rect.left;
    int sy = rect.top;
 
    const CPoint offset = GetPopupOffset();
    sx += offset.x;
    sy += offset.y;
 
    int cx = rect.Width();
    int cy = rect.Height();
 
    CImage Image;
    (void)Image.Create(cx, cy, ScrDC.GetDeviceCaps(BITSPIXEL));
    CDC* pDC = CDC::FromHandle(Image.GetDC());
    (void)pDC->BitBlt(00, cx, cy, &ScrDC, sx, sy, SRCCOPY);
    Image.ReleaseDC();
 
    CString str_save;
    str_save = file_name;
    long result = Image.Save(str_save, Gdiplus::ImageFormatPNG);
 
    if (result < 0)
    {
        (void)AfxMessageBox(_T("캡쳐 오류"));
    }
}
 
 
void CPrintTestDlg::PrintOutImage(CString file_name)
{
    int nWidth, nHeight;
    CClientDC dc(this);//this->pImgWnd
    CDC MemDC;
    MemDC.CreateCompatibleDC(&dc);
 
    CRect rect;
    GetClientRect(rect);
    nWidth = rect.Width();
    nHeight = rect.Height();
 
    CBitmap BMP;
 
    CImage image;
    image.Load(file_name);
    if (image.IsNull() == false)
    {
        int si = image.GetWidth();
        int sih = image.GetHeight();
        BMP.Attach(image.Detach());
 
        HANDLE hDib;
        LPSTR pDib;
        LPBITMAPINFO lpBitInfo;
        HANDLE hlpBitInfo;
 
        hDib = GlobalAlloc(GHND, nWidth*nHeight * 3);
        pDib = (LPSTR)GlobalLock(hDib);
        hlpBitInfo = GlobalAlloc(GHND, sizeof(BITMAPINFOHEADER) + sizeof(BITMAPINFO));
        lpBitInfo = (LPBITMAPINFO)GlobalLock(hlpBitInfo);
 
        lpBitInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
        lpBitInfo->bmiHeader.biWidth = nWidth;
        lpBitInfo->bmiHeader.biHeight = nHeight;
        lpBitInfo->bmiHeader.biPlanes = 1;
        lpBitInfo->bmiHeader.biBitCount = 24;
        lpBitInfo->bmiHeader.biCompression = BI_RGB;
        lpBitInfo->bmiHeader.biSizeImage = nWidth * nHeight * 3;
        lpBitInfo->bmiHeader.biXPelsPerMeter = 0;
        lpBitInfo->bmiHeader.biYPelsPerMeter = 0;
        lpBitInfo->bmiHeader.biClrUsed = 0;
        lpBitInfo->bmiHeader.biClrImportant = 0;
 
        HDC hdc = ::GetDC(this->m_hWnd);
        GetDIBits(hdc, (HBITMAP)BMP, 0, nHeight, pDib, lpBitInfo, DIB_RGB_COLORS);
        ::ReleaseDC(this->m_hWnd, hdc);
 
        static DOCINFO docinfo = { sizeof(DOCINFO), _T("프린트"), NULL };
 
 
        //팝업창 안띠우고 기본 설정 프린터로 인쇄
        //CPrintDialog dlg(TRUE, PD_RETURNDEFAULT);
        //dlg.DoModal();
 
        //팝업창 뛰우고 프린터 선택해서 인쇄
        CPrintDialog dlg(FALSE);
        if (dlg.DoModal() == IDCANCEL)
        {
 
        GlobalUnlock(hDib);
        GlobalFree(hDib);
        GlobalUnlock(hlpBitInfo);
        GlobalFree(hDib);
 
        DeleteObject(BMP.m_hObject);
 
        DeleteDC(MemDC.m_hDC);
        DeleteDC(dc.m_hDC);
 
        return;
        }
 
 
        DEVMODE *pDevmode = (DEVMODE*)dlg.GetDevMode();
        pDevmode->dmOrientation = 2;
        
        HDC hpdc = dlg.CreatePrinterDC();
 
        int cy = GetDeviceCaps(hpdc, VERTRES);
        int cx = GetDeviceCaps(hpdc, HORZRES);
 
        if (StartDoc(hpdc, &docinfo))
        {
            if (StartPage(hpdc))
            {
                StretchDIBits(hpdc,
                    00, cx, cy, 0, nHeight - sih, si, sih, pDib, lpBitInfo, DIB_RGB_COLORS, SRCCOPY);
                //image.StretchBlt(image.GetDC(), 0, 0, nWidth, nHeight, SRCCOPY);
                EndPage(hpdc);
            }
            EndDoc(hpdc);
        }
 
        GlobalUnlock(hDib);
        GlobalFree(hDib);
        GlobalUnlock(hlpBitInfo);
        GlobalFree(hlpBitInfo);
 
        DeleteObject(BMP.m_hObject);
 
        DeleteDC(dc.m_hDC);
        DeleteDC(MemDC.m_hDC);
        ::RestoreDC(hpdc, -1);
    }
}
cs

GetExecutedPath(); // 실행 파일 경로 확인
GetPopupOffset(); // 듀얼 모니터 좌표인식
Capture(CString file_name); : 화며 캡쳐 및 이미지 저장
PrintOutImage(CString file_name); : 출력

 

 

[소스파일 다운로드] 아래

PrintTest.zip
3.48MB

300x250
반응형
300x250
반응형

 

 

 

아래는 ANSI 문자열에서 유니코드로의 변환 방법코드다.(MultiByteToWideChar)

 

여기서 SysAllocStringLen를 사용해서 메모리 할당 하게되면

SysFreeString로 메모리를 해제 해야 메모리가 올라가지 않는다.

(옛날 코드 보면 SysFreeString 없이 사용하기도 하는데 메모리 반환이 언제되는지 모름)

 // sTime이란 ANSI 문자열을 bstr이란 이름의 유니코드(BSTR 타입) 변수로 변환
 char sTime[] = "유니코드 변환 예제";
 BSTR bstr;
 // sTime을 유니코드로 변환하기에 앞서 먼저 그 길이를 알아야 한다.
 int nLen = MultiByteToWideChar(CP_ACP, 0, sTime, lstrlen(sTime), NULL, NULL);
 // 얻어낸 길이만큼 메모리를 할당한다.
 bstr = SysAllocStringLen(NULL, nLen);
 
 // 이제 변환을 수행한다.
 MultiByteToWideChar(CP_ACP, 0, sTime, lstrlen(sTime), bstr, nLen);
 
// 필요없어지면 제거한다.
SysFreeString(bstr);

 

 

 

300x250
반응형
300x250
반응형

https://robotbef.tistory.com/19

 

MATLAB함수 C에서 불러 사용하기(Engine) + C코드로 짠 함수 Matlab에서 사용하기!(MEX)

MATLAB처럼 몇가지 함수를 불러서 C언어에서 MATLAB처럼 이용할 수 있다면 얼마나 좋겠습니까. C언에서 제공되는 라이브러리가 이렇다면 MATLAB이 설 자리가 없어지겠죠. C언어에서 제공되는 math에는

robotbef.tistory.com

 

300x250
반응형

'기타 > 링크' 카테고리의 다른 글

코딩팩토리 - 코딩 블로그  (0) 2022.06.16
위키독스 - 온라인 책을 제작 공유하는 플랫폼 서비스  (0) 2022.06.16
https://colorscripter.com/  (0) 2022.05.05
Python으로 프로그램 제어  (0) 2022.04.27
플러터  (0) 2022.04.17
300x250
반응형

 

소수점 처리하는 함수에 대하여 단순히 반올림, 올림, 내림, 버림으로 외우고 있다면,

아래 정수를 선택하는 방향에 대해 숙지를 하는게 좋다.

 

만약 기존처럼 

ceil = 올림, floor = 내림 으로 알고만 있다면

(-)음수 처리 시 실수 할 수 있다.

버림 floor(-2.6) 은 -2 가 되는게 아니라 -3이 된다.

 

 

round() 반올림

가장 가까운 정수 선택

round(2.1)   // 결과 : 2
round(-2.6)  // 결과 : -3

 

ceil() 올림

+(양수) 방향으로 가까운 정수 선택

ceil(2.1);  // 결과 : 3
ceil(-2.6); // 결과 : -2

 

floor() 내림

-(음수) 방향으로 가까운 정수 선택

floor(2.1);  // 결과 : 2
floor(-2.6); // 결과 : -3

 

trunc() 버림

0의 방향으로 가까운 정수 선택

trunc(2.1);  // 결과 : 2
trunc(-2.6); // 결과 : -2

 

 

 

300x250
반응형

'윈도우 프로그래밍 > C, C++, MFC' 카테고리의 다른 글

SysAllocStringLen 메모리 해제  (0) 2022.06.07
MFC KEY CODE 표  (0) 2022.06.02
Matlab fix c변환  (0) 2022.05.25
지원되지 않는 작업을 시도했습니다.  (0) 2022.05.16
c++ 함수 const 위치별 차이  (0) 2021.12.25
300x250
반응형

이 메시지는 리소스 아이디가 없을때 발생 합니다.

 

먼저 확인해 볼수 있는건

 

DoDataExchange 함수안에  IDC_ 이름 값이 없거나 겹치는 부분을 확인 하시기 바랍니다.

    DDX_Control(pDX, IDC_COMBO1, m_combo_water_column);
    DDX_Control(pDX, IDC_EDIT4, m_down_factor);
    DDX_Control(pDX, IDC_BUTTON1, m_btn_applay);
    DDX_Control(pDX, IDC_EDIT_SMOOTHING, m_smoothing);
    DDX_Control(pDX, IDC_EDIT_BASE, m_base);
    DDX_Control(pDX, IDC_EDIT_ALTITUDE, m_altitude);

 

300x250
반응형
300x250
반응형

UDP Multicast 테스트 프로그램 입니다.

1. 전송할 랜카드를 선택해 주세요(중요)

2. IP, PORT 입력 후 연결 클릭

3. 하단에 전송할 내용 입력 후 송신을 누르면 됩니다.

 

UDP Multicast 아이피 범위는 시작이 224 ~ 239로 시작해야 합니다.

(프로그램은 visual studio 2015로 제작되었습니다.)

 

 

 프로그램 다운로드(아래) 

Multicast Test.zip
0.07MB

 

 

[ 랜카드 목록 검색]

#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")
#include <vector>

    std::vector<std::string> vector_ethernet;
    std::vector<std::string> vector_ip;


    // 현재 연결된 인터넷에서 검색
    PIP_ADAPTER_INFO pAdapterInfo;
    pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
    ULONG buflen = sizeof(IP_ADAPTER_INFO);

    if (GetAdaptersInfo(pAdapterInfo, &buflen) == ERROR_BUFFER_OVERFLOW) {
        free(pAdapterInfo);
        pAdapterInfo = (IP_ADAPTER_INFO *)malloc(buflen);
    }

    if (GetAdaptersInfo(pAdapterInfo, &buflen) == NO_ERROR) {
        PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
        while (pAdapter)
        {
            vector_ethernet.push_back(pAdapter->Description);
            vector_ip.push_back(pAdapter->IpAddressList.IpAddress.String);

            pAdapter = pAdapter->Next;
        }
    }

위의 코드 적용 시

vector_ethernet 에는 랜카드 이름이

vector_ip 는 랜카드 ip가 추가됩니다.

 

 

 

 

[ 랜카드 선택]

IN_ADDR localaddr;
localaddr.s_addr = inet_addr(find_address.c_str());
int result_select = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, (char*)&localaddr, sizeof(localaddr));

IP_ADD_MEMBERSHIP 을 사용해서 그룹에 조인 후에 사용해야 합니다.

 

 

아래 연결하는 풀 코드를 확인해 보세요

#include <string>
#include <WS2tcpip.h>

#include <iphlpapi.h>
#pragma comment(lib, "iphlpapi.lib")

 

SOCKET socket_;
SOCKADDR_IN sock_addr{};
struct ip_mreq mreq{};

bool NetFrame::Create(const std::string &a_ip, const int a_port, const std::string &select_ip)
{
    bool result = false;

    closesocket(socket_);

    int nSocketType = SOCK_DGRAM;
    socket_ = socket(PF_INET, nSocketType, 0);

    if (socket_ != INVALID_SOCKET)
    {
        sock_addr.sin_family = AF_INET;
        sock_addr.sin_port = htons(static_cast<u_short>(a_port));
        sock_addr.sin_addr.s_addr = INADDR_ANY;

        int optval = 1;

        setsockopt(socket_, SOL_SOCKET, SO_REUSEADDR, (char*)&optval, sizeof(optval));

        if (bind(socket_, reinterpret_cast<SOCKADDR*>(&sock_addr), sizeof(sock_addr)) == 0)
        {
            result = true;

            if (false) // 내가 송신한 데이터는 안들어 오도록 설정
            {
                // https://wiki.kldp.org/HOWTO/html/Multicast/Multicast-HOWTO-6.html
                char loop = 0;
                int ret_val = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop));
            }

            //
            // Multicast 이더넷 선택 로직
            //
            //1. 멀티캐스트 라우터 테이블 추가
            mreq.imr_multiaddr.S_un.S_addr = inet_addr(a_ip.c_str());
            if (select_ip.empty())
                mreq.imr_interface.s_addr = htonl(INADDR_ANY);
            else
                mreq.imr_interface.s_addr = inet_addr(select_ip.c_str());
            int result_join = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char*)&mreq, sizeof(mreq));
            if (result_join < 0)
                result = false;

            //2. 통신 인터페이스 선택(어떤걸 사용할 것인가)
            if (select_ip.empty() == false)
            {
                IN_ADDR localaddr;
                localaddr.s_addr = inet_addr(select_ip.c_str());
                int result_select = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF, (char*)&localaddr, sizeof(localaddr));
                if (result_select < 0)
                    result = false;
            }
        }

        inet_pton(sock_addr.sin_family, a_ip.c_str(), &sock_addr.sin_addr.s_addr);
    }

    return result;
}


std::string ip

std::ethernet_ip;
int net_port; 

 

Create(ip, port, ethernet_ip);

 

 

 

 

[ Wireshark로 전송 및 수신 확인]

랜카드 선택하는 부분은 예를들어 노트북에 랜카드가 연결되어있고 Wifi

이렇게 이더넷이 2개 연결된 상태에서

 

랜은 선택하는 설정을 안하면 멀티캐스트 전송 시

둘다 전송하는게 아니라 제일처음 전송한 2개중 1개로 계속 전송 하는 문제가 있습니다.

아래 그림처럼 이더넷, 이더넷 4 중 한곳으로 전송 됩니다.

 

이더넷 을 더블클릭 하시면 앞에 파란 버튼을 누르면 패킷 캡쳐가 시작됩니다.

udp로 검색을 하시면 UDP 데이터만 보여지게 되는데

아래 목록을 더블클릭 하시면 새창으로 정보를 확인할 수 있습니다.

 

아래 그림 처럼 Wireshark로 데이터 패킷을 확인해 보시면 어디로가는지 확인할 수 있습니다.

 

 

[기타 OS 없는 장비 전송 방법]

Dst 부분에 IPv4mcast로 되어 있어야 멀티 캐스트 전송입니다.

Dst Mac Adress는 01:05:5e 까지 나와야 합니다.

 

(OS가 있는 컴퓨터가 아닌 다른 펌웨어 기반 장비 개발은 아래와 같이 송신 아이피로 MAC Adress를 입력해줘야 전송이 되더라구요)

Mac Adress 계산은 

http://www.dqnetworks.ie/toolsinfo.d/multicastaddressing.html 사이트에서 보시면 될것 같습니다.

 

 

 

 

 

[정보가 도움이 되셨다면 광고 배너 클릭이 글쓴이의 활력이 됩니다.]

감사합니다.

 

 

 

 

 

300x250
반응형
300x250
반응형

[ 오류 내용 ]

MSB4175 "C:\Program Files (x86)\MSBuild\14.0\bin\Microsoft.Build.Tasks.Core.dll" 어셈블리에서 "CodeTaskFactory" 작업 팩터리를 로드할 수 없습니다.파일에 바이러스 또는 기타 사용자 동의 없이 설치된 소프트웨어가 있기 때문에 작업이 완료되지 않았습니다.

 

window 관련 defender 업데이트 이후 생긴 원인 입니다.

 

 

 

[ 해결 방법 ]

아래와 같이 윈도우 검색기 -> Window 보안 선택

 

 

바이러스 및 위협 방지 -> 실시간 보호 끄기 선택

300x250
반응형

'윈도우 프로그래밍' 카테고리의 다른 글

window 프로그램 꺼지면 재실행  (2) 2022.03.31
300x250
반응형
	double check_value = 0;

	//0이 아니면
	if (fabs(check_value) > std::numeric_limits<double>::epsilon())
	{
		
	}

	//0이면
	if (fabs(check_value) < std::numeric_limits<double>::epsilon())
	{
		
	}

 

[정보가 도움이 되셨다면 광고 배너 클릭이 글쓴이의 활력이 됩니다.]

감사합니다.

300x250
반응형

'윈도우 프로그래밍 > 코딩규칙' 카테고리의 다른 글

c++ double, float 값 비교  (0) 2020.07.21

+ Recent posts