300x250
반응형

 

 

아래 site_name에 주소만 변경해서 코드를 넣으면 바로 웹사이트가 뜹니다.

브라우저는 윈도우에서 기본으로 설정된 브라우저로 실행되니 참고해주세요.

HINSTANCE hResult;
hResult = NULL;
CString site_name;
site_name = "https://www.naver.com";
hResult = ShellExecute(NULL, _T("open"), site_name, NULL, NULL, SW_SHOW);

 

2023년 어느겨울에..

 

 

 

 

300x250
반응형
300x250
반응형

 

 

 

중복 실행 막는 방법은 대략 아래와 같이 3가지 방법이 있다고 합니다.

 

1. 프로세스 목록에서 프로그램 이름을 확인해서 막는 방법

2. Mutex를 사용한 방법

3. 공유메모리를 사용한 방법

 

저는 Mutex를 사용한 방법이 좋다고 해서 자주 사용하는데 이 방법으로 중복 실행을 막는 방법에 대해서 설명 할께요.

간단합니다.

 

MFC 프로그램 코드를 봅시다.

프로젝트 이름이 Test 라는 프로젝트로 만들었다면, CTestApp::InitInstance() 라는 함수가 있어요.

 

 

아래 예시 코드를 보면

기존 함수 제일 위에

7줄의 return 코드를 넣어주세요. 바로 이해가 될것이라고 생각 됩니다.

TestApp은 체크할 프로그램 이름과 일치할 필요는 없어요.  다른 프로그램 이름과 안겹치게 유니크 하게 작성해 주세요

BOOL CTestApp::InitInstance()
{
	// 추가해야 하는 코드
	HANDLE hMutex = NULL;
	hMutex = CreateMutex(NULL, TRUE, _T("TestApp"));
	if (GetLastError() == ERROR_ALREADY_EXISTS)
	{
		AfxMessageBox(_T("프로그램이 이미 실행 중입니다."));
		return FALSE;
	}


	// 밑에는 기존 코드
    //
    //
    //
    //
       
    return FALSE;
}

이상입니다.

 

 

좋은 프로그램 만드세요.

2023년 어느 겨울 작성.

 

 

 

300x250
반응형
300x250
반응형

프로그램 및 코드 다운로드

2. Example_OpenGL_EBO_VAO_VBO.zip
7.74MB

주요 코드는 아래와 같습니다.

#pragma once
#include "GlRender.h"

class RenderEBO_VAO_VBO : public GlRender
{
public:
    RenderEBO_VAO_VBO();
    ~RenderEBO_VAO_VBO();
    
private:
    void GlInit() override;
    void GlDraw() override;

    float vertices[4] = {
        0,10,
        200, 110
    };
    float vertices2[4] = {
        0,20,
        200, 120
    };


    GLuint VAO;
    GLuint VAO2;

    GLuint VBO;
    GLuint VBO2;


    GLuint EBO;
    GLuint VAO3;
    GLuint VBO3;


    float vertices3[12] = {
        50.5f,  50.5f, 0.0f,  // 우측 상단
        50.5f, -50.5f, 0.0f,  // 우측 하단
        -50.5f, -50.5f, 0.0f,  // 좌측 하단
        -50.5f,  50.5f, 0.0f   // 좌측 상단
    };
    unsigned int indices[6] = {  // 0부터 시작한다는 것을 명심하세요!
        0, 1, 3,   // 첫 번째 삼각형
        1, 2, 3    // 두 번째 삼각형
    };

};

 

아래 코드에서는 VAO + VBO를 2개 만들어서 2개의 라인을 그립니다.

그리고 EBO + VAO + VBO를 사용하여 정점 좌표를 인덱싱하여 순서를 변경 합니다.

위에 헤더의 indices를 주목해 주세요.

0~4 사이의 순서를 변경하면 LINE_STRIP 그리는 위치가 바뀌게 됩니다.

void RenderEBO_VAO_VBO::GlInit()
{    
    /***************************************************************************************
    * VAO + VBO 1번째
    **************************************************************************************/
    // VAO 생성 및 바인딩
    glGenVertexArrays(1, &VAO);  // 1.할당 (앞에 인자는 1개 의미)
    glBindVertexArray(VAO);

    // VBO
    // 1. Gen(할당) -> 2. Bind(바인딩) -> 3. Data(입력) -> 4. Link 순서로 사용
    glGenBuffers(1, &VBO);  // 1.할당 (앞에 인자는 1개 의미)
    glBindBuffer(GL_ARRAY_BUFFER, VBO); // 2. GL_ARRAY_BUFFER 형식 바인딩 (이 버퍼 말고도 종류가 많음)
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STREAM_DRAW); // 3.데이터 복사 및 크기 설정
    ///GL_STATIC_DRAW: 데이터가 거의 변하지 않습니다.
    ///GL_DYNAMIC_DRAW: 데이터가 자주 변경됩니다.
    ///GL_STREAM_DRAW: 데이터가 그려질때마다 변경됩니다.

    // 4. Link Vertex Attribute
    int location = 0;
    glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GL_FLOAT), (void*)0);
    glEnableVertexAttribArray(location);



    /***************************************************************************************
    * VAO + VBO 2번째
    **************************************************************************************/
    // VAO 생성 및 바인딩
    glGenVertexArrays(1, &VAO2); // 1.할당 (앞에 인자는 1개 의미)
    glBindVertexArray(VAO2); // VAO를 OpenGL context에 연결(bind)

    // VBO
    // 1. Gen(할당) -> 2. Bind(바인딩) -> 3. Data(입력) -> 4. Link 순서로 사용
    glGenBuffers(1, &VBO2);   // 1.할당 (앞에 인자는 1개 의미)
    glBindBuffer(GL_ARRAY_BUFFER, VBO2); // 2. GL_ARRAY_BUFFER 형식 바인딩 (이 버퍼 말고도 종류가 많음)
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices2), vertices2, GL_STREAM_DRAW); // 3.데이터 복사 및 크기 설정
    ///GL_STATIC_DRAW: 데이터가 거의 변하지 않습니다.
    ///GL_DYNAMIC_DRAW: 데이터가 자주 변경됩니다.
    ///GL_STREAM_DRAW: 데이터가 그려질때마다 변경됩니다.

    // 4. Link Vertex Attribute
    glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GL_FLOAT), (void*)0);
    glEnableVertexAttribArray(location);



    /***************************************************************************************
     * EVO + VAO + VBO
     **************************************************************************************/
    // VAO 생성 및 바인딩
    glGenVertexArrays(1, &VAO3);  // 1.할당 (앞에 인자는 1개 의미)
    glBindVertexArray(VAO3);  // VAO를 OpenGL context에 연결(bind)

    // VBO
    // 1. Gen(할당) -> 2. Bind(바인딩) -> 3. Data(입력) -> 4. Link 순서로 사용
    glGenBuffers(1, &VBO3);   // 1.할당 (앞에 인자는 1개 의미)
    glBindBuffer(GL_ARRAY_BUFFER, VBO3);  // 2. GL_ARRAY_BUFFER 형식 바인딩 (이 버퍼 말고도 종류가 많음)
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices3), vertices3, GL_STREAM_DRAW); // 3.데이터 복사 및 크기 설정

    // OpenGL이 사용하기 위해 인덱스 리스트를 element 버퍼에 복사
    glGenBuffers(1, &EBO);
    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, EBO);
    glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(indices), indices, GL_STREAM_DRAW);
    ///GL_STATIC_DRAW: 데이터가 거의 변하지 않습니다.
    ///GL_DYNAMIC_DRAW: 데이터가 자주 변경됩니다.
    ///GL_STREAM_DRAW: 데이터가 그려질때마다 변경됩니다.

    // Link Vertex Attribute
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 3 * sizeof(float), (void*)0);
    glEnableVertexAttribArray(0);
}

 

void RenderEBO_VAO_VBO::GlDraw()
{
    glViewport(0, 0, gl_window_width, gl_window_height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho((double)-gl_window_width / 2, (double)gl_window_width / 2,
        (double)-gl_window_height / 2, (double)gl_window_height / 2,
        1, -1);
    
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0, 0, 0, 0);


    glBindVertexArray(VAO);	// 한 줄로 끝!
    glColor4f(0, 1, 0, 1);
    glDrawArrays(GL_LINES, 0, 2);


    glBindVertexArray(VAO2);	// 한 줄로 끝!
    glColor4f(0, 0, 1, 1);
    glDrawArrays(GL_LINES, 0, 2);


    glBindVertexArray(VAO3);	// 한 줄로 끝!
    glColor4f(0, 0, 1, 1);
    glDrawElements(GL_LINE_STRIP, 6, GL_UNSIGNED_INT, 0); // EBO 사용 시 glDrawElements로 출력
}
300x250
반응형
300x250
반응형

프로그램 및 코드 다운로드

1. Example_OpenGL_VBO.zip
7.73MB

 

주요 코드는 아래와 같습니다.

 

Header

class RenderVBO : public GlRender
{
public:
    RenderVBO();
    ~RenderVBO();

    GLuint VBO;

    float vertices[8] = {
        0,10,
        200, 110,
        -0,-10,
        -200,-110
    };


private:
    void GlInit() override;
    void GlDraw() override;
};

 

 

CPP

void RenderVBO::GlInit()
{
    // 1. Gen(할당) -> 2. Bind(바인딩) -> 3. Data(입력) -> 4. Link 순서로 사용

    glGenBuffers(1, &VBO); // 1.할당
    glBindBuffer(GL_ARRAY_BUFFER, VBO); // 2. GL_ARRAY_BUFFER 형식 바인딩 (이 버퍼 말고도 종류가 많음)
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices) /* Byte 크기*/ , &vertices[0], GL_STREAM_DRAW); // 3.데이터 복사 및 크기 설정
    ///GL_STATIC_DRAW: 데이터가 거의 변하지 않습니다.
    ///GL_DYNAMIC_DRAW: 데이터가 자주 변경됩니다.
    ///GL_STREAM_DRAW: 데이터가 그려질때마다 변경됩니다.

    // 4. Link Vertex Attribute
    int location = 0;

    // 파라미터 : location, 크기, 데이터 형태(float 등), Normalize 여부, 한점 BYTE 크기 (0이면 자동 계산), 시작 인덱스
    glVertexAttribPointer(location, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(GL_FLOAT), (void*)0);
    glEnableVertexAttribArray(0);

}

VBO를 사용하기 위해서는 아래순서로 사용합니다. 꼭 기억해두세요.

1. Gen(할당) -> 2. Bind(바인딩) -> 3. Data(입력) -> 4. Link 순서로 사용

 

 

void RenderVBO::GlDraw()
{
    glViewport(0, 0, gl_window_width, gl_window_height);
    glLoadIdentity();

    glOrtho((double)-gl_window_width / 2, (double)gl_window_width / 2,
        (double)-gl_window_height / 2, (double)gl_window_height / 2,
        1, -1);
    

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0, 0, 0, 0);


    glColor4f(0, 1, 0, 1);

    // 중요! 단독으로 VBO만 사용시 VBO버퍼에 마지막으로 입력된 데이터가 출력됨
    // 만약 여러 데이터를 입력하려면 VAO를 같이 사용해야 함(다음 예제 참조)
    glDrawArrays(GL_LINES, 0, 2); // glBegin(GL_LINES); 처럼 쓰면됨 GL_POINTS 등등
    
}

glDrawArrays로 버퍼에 저장된 데이터를 출력하였습니다.

 

300x250
반응형
300x250
반응형

 

 

 

 

 

이번 내용은 OpenGL을 윈도우 창과 연동하는 방법을 작성하였습니다.

 

주 내용은 간단합니다.

예제 파일에 있는 GlRender.cpp, GlRender.h 파일을 사용해서 

GlRender클래스는 자체 OpenGLCreate 관련 함수와, 쓰레드 생성 함수들이 있습니다.

나중에 GlStart()를 호출하게되면 MFC 화면에 영상이 출력됩니다.

 

RenderTest라는 클래스를 만들었습니다.

 

 

RenderTest.h

#pragma once
#include "GlRender.h"

class RenderTest : public GlRender
{
public:
    RenderTest();
    ~RenderTest();
    
private:
    void GlInit() override;
    void GlDraw() override;
};

헤더는 GlRender를 상속받습니다.

GlRender 클래스에 가상함수로 호출되기 때문에 GlInit(), GlDraw() 함수는 오버라이드! 

 

RenderTest.cpp

#include "stdafx.h"
#include "RenderTest.h"


RenderTest::RenderTest(){}

RenderTest::~RenderTest(){}

void RenderTest::GlInit(){}

void RenderTest::GlDraw()
{
    glViewport(0, 0, gl_window_width, gl_window_height);

    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    glOrtho((double)-gl_window_width / 2, (double)gl_window_width / 2,
        (double)-gl_window_height / 2, (double)gl_window_height / 2,
        1, -1);


    glMatrixMode(GL_MODELVIEW);

    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
    glClearColor(0, 0, 0, 0);


    glEnable(GL_BLEND);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);

    glPushMatrix();
    {
        glBegin(GL_LINES);

        glColor4f(0, 1, 0, 1);
        glVertex2d(0, 0);
        glVertex2d(200, 100);

        glEnd();
    }
    glPopMatrix();
    glDisable(GL_BLEND);



    glMatrixMode(GL_MODELVIEW);
    glMatrixMode(GL_PROJECTION);

}

 

RenderTest의 GlDraw() 함수 내용을 보면

중요한 내용은 아니지만 대략적으로 설명을 해보겠습니다.

 

1. glViewport를 사용하여 그릴 화면 영역을 잡고

2. 공간 메트릭스 행렬 초기화

3. glOrtho를 사용하여 화면 Viewport 영역 좌표계를 설정 했습니다.

4. GL_BLEND를 사용하여 투명도 적용

 

GlBegin ~ GlEnd() 내용에 색상을 정하고, 점2개로 직선을 그리는 OpenGL 코드를 작성하였습니다.

 

 

이제 MFC 화면에 연동을 해볼께요

 

0. stdafx.h에 OpenGL 환경설정 추가

#pragma comment ( lib, "OpenGL32.lib" )

#ifdef _WIN32
#include "OpenGL_lib/core/x86/glew.h"
#include "OpenGL_lib/core/x86/wglew.h"
#endif

#ifdef _WIN64
#include "OpenGL_lib/core/x64/glew.h"
#include "OpenGL_lib/core/x64/wglew.h"
#endif

 

1. 먼저 출력할 Dialog 클래스 헤더에 객체 선언

    RenderTest m_render_test;

 

2.  OnInitDialog() 함수에

m_render_test.Create(this);
m_render_test.GlStart();

 

3. OnSize() 함수에

m_render_test.GlResize(cx, cy);

 

4. OnClose() 함수에

m_render_test.GlClose();

 

 

프로그램을 실행한 결과!

 

예시 코드는 아래에서 받을 수 있습니다.

1. Example_OpenGL_MFC.zip
8.23MB

VisualStudio 2012에서 작성되었습니다.

300x250
반응형
300x250
반응형

 

이번 예제는 현재 위치에 파일이 있는지 확인하는 코드 입니다.

CString full_path = GetExecutedPath() + _T("test/file.tmp");

if (INVALID_FILE_ATTRIBUTES == GetFileAttributes(full_path) && GetLastError() == ERROR_FILE_NOT_FOUND)
{
	AfxMessageBox(_T("파일 X"));
}
else
{
	AfxMessageBox(_T("파일 O"));        
}

GetExcutedPath() 함수는 실행파일이 있는 위치를 리턴해 줍니다.

저걸 사용안하면 프로젝트 소스가 있는 위치에서 파일을 확인하기 때문에 ㅋ

아래 함수를 그대로 복사해서 붙여넣기 하시면 됩니다.

CString 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;
}

 

 

간단하쥬 ㅋ

300x250
반응형
300x250
반응형

 


아래 코드는 파일이름 변경 예제 입니다. 아래 2가지 방법중 하나를 사용하시면 됩니다.

아래 예제는 file.tmp 라는 파일을 file.xtf 로 확장자 / 이름 변경 하는 코드 입니다.

 

1. C 코드를 사용한 변환

CString full_path_tmp = GetExecutedPath() + _T("test/file.tmp");
CString full_path_xtf = full_path_tmp;        
full_path_xtf.Replace(_T(".tmp"), _T(".xtf"));


CStringA a_full_path_tmp = (CStringA)full_path_tmp;
CStringA a_full_path_xtf = (CStringA)full_path_xtf;

const char* char_path = a_full_path_tmp.GetBuffer();
const char* char_path_changed = a_full_path_xtf.GetBuffer();

rename(char_path, char_path_changed);

C 코드인 rename을 사용합니다.

해당 파라미터는 const char*를 인자로 사용하기 때문에 변환해서 넣어야 합니다.

장점은 오류 예외창이 안뜹니다.

 

 

2. MFC 코드는 사용한 변환

CString full_path_tmp = GetExecutedPath() + _T("test/file.tmp");
CString full_path_xtf = full_path_tmp;        
full_path_xtf.Replace(_T(".tmp"), _T(".xtf"));

CFile::Rename(full_path_tmp, full_path_xtf);

MFC 함수인 CFile::Rename 함수를 사용합니다.

해당 파라미터는 CString을 그대로 사용하시면 됩니다.

단점은 파일이 없을경우 오류 메시지창이 뜹니다.

 

 

간단하쥬 ㅋ

300x250
반응형
300x250
반응형

 

 

문자집합은 유니코드 기반 코드 입니다.

 

아래 코드는 CStringA로 형변환 후 GetBuffer()를 사용하여 변환하는 예제입니다.

CString file_name = _T("filename.dat");
CStringA a_file_name = (CStringA)file_name;

const char* ptr_name = a_file_name.GetBuffer();

 

아주 간단 하쥬 ㅋ

 

 

300x250
반응형

+ Recent posts