레이블이 VIsual Studio인 게시물을 표시합니다. 모든 게시물 표시
레이블이 VIsual Studio인 게시물을 표시합니다. 모든 게시물 표시

2025년 1월 28일 화요일

Visual Studio C++ Resource View Blank(비어 있을때)

 안녕하세요

Visaul Studio Studio 버젼별 사용하다 설치를 새로 했을때

C++ 프로젝트의 경우 리소스 뷰(Resource View) 가 안나올때가 있습니다.

그때 아래 경로에서 옵션을 확인 합니다.(영문버젼 기준)

Tools -> Options -> Text Editor -> C++ -> Advanced 항목중에

"Disable Database" 항목이 False 값을 가지고 있어야 합니다.

​

항목을 값을 변경하시고 다시 보면 잘 나올겁니다. 그럼~

Visual Studio Resource 영문 입력 간격 오류

 안녕하세요

오늘은 개발을 하다가 원치 않은 결과가 발생을 하여 당황할일이 있고 그에 대한 해결책중 하나 입니다.

Visaul Studio Resource 입력창에서 영문 입력하다가 영어 문자 사이 간격이 UniCode 입력하는것처럼 벌어지는 경우가 발생합니다.

이때 당황 하지 마시고 "Alt" + "= " 이 조합키를 누르시면 다시 정상적으로 돌아갑니다. ^^

2022년 8월 12일 금요일

Visual Studio 소스 파일 오픈 에러 대응

 윈도우가 업데이트 되거나 하드 디스크 정리 하고 난후 캐쉬가 뒤죽박죽 되어 정상적으로 열리던 소스 파일들이 아래와 같은 에러 발생하면서 안 열리는 경우가 있다.

"no exports were found that match the constraint"

​

이럴때는 아래 경로 둘중에 하나를 찾아가서 캐쉬 파일을 정리 해주면 된다.

%LocalAppData%\Microsoft\VisualStudio\11.0\ComponentModelCache

또는

%LocalAppData%\Microsoft\VPDExpress\11.0\ComponentModelCache

폴더명 안에 버젼은 Visual Studio 버젼별로 나오기 때문에 자신이 쓰는 VIsual Studio 버젼을 아래에서 확인하고

해당 경로에 가서 지워주고 난후

Visual Studio 를 재실행 주면 된다.

​

Visual Studio 2008 is 9.0

Visual Studio 2010 is 10.0

Visual Studio 2012 is 11.0

Visual Studio 2013 is 12.0

Visual Studio 2015 is 14.0

Visual Studio 2017 is 15.0

Visual Studio 2019 is 16.0

​

그럼 ^^

2020년 11월 1일 일요일

std::string replace all

 std::string 을 처음으로 접해보지 않은 저로서는 그냥 쓰다 보면
다른 FrameWork에서는 그냥 제공하는 함수도 없다는 점이 불편하네요.
물론 최신 라이브러리에서 제공은 하는지는 모르지만 가끔은 이전 버젼에서 작업을 해야 되서​

문자열 전체에서 특정 문자를 변경해야 하는 작업입니다.
일단 소스를 보시죠~


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
void ReplaceStdString(std::string& sOrg, const char* szOld, const char* szNew)
{
	std::string::size_type nPos = 0;
	std::string::size_type nOffset = 0;

	std::string sPattern = szOld;
	std::string sReplace = szNew;

	while ((nPos = sOrg.find(sPattern, nOffset)) != std::string::npos)
	{
		sOrg.replace(sOrg.begin() + nPos, sOrg.begin() + nPos + sPattern.size(), sReplace);
		nOffset = nPos + sReplace.size();
	}
}

<위 코드는 Visual Studio 2008  Window 10 64bit 환경에서 빌드 되었습니다 >
​

위 소스를 보시면 sOrg라는 변수에 전체 문자열이 들어오고 szOld는 변경할 문자
szNew는 변경 되어야할 문자를 입력 받습니다.
전체 문자열을 뒤지면서 하나씩 찾아 변경하는 로직입니다.

std::string 에서 제공하는 replace 는 시작 index와 끝 index를 찾아 변경될 문자열을 찾아 변경하는 함수 입니다.
​

그럼 ^^

2020년 6월 8일 월요일

Visual Studio Code C/C++ 개발환경 구축(Windows)

간단히 C/C++ 개발 환경을 구축하는 법을 설명할까 합니다.

​www.stackoverflow.com 에서 설문시 가장 많이 쓰는 개발 툴로 Visaul Studio Code가 50%넘게 투표 되었기 때문에 위 툴로 설명할까 합니다.


시작에 앞서 두개의 툴을 설치 하셔야 합니다.

첫번째로 Visual Studio Code를 설치 하세요.

https://code.visualstudio.com/download

해당 페이지에 가셔서 "Windows" 용으로 설치 하시면 됩니다.


두번째로 gcc 컴파일러를 설치 해야 하기 때문에

http://mingw-w64.org/doku.php/download

위 페이지에 가셔서 아래 그림에 해당 하는것을 설치 하시기 바랍니다.











설치파일을 실행 하시면 아래와 같은 환경으로 설치 하세요.












컴파일러 설치가 끝나면 컴맨드창에서 명령어를 실행해야 하기 때문에 환경 변수를 등록합니다.

탐색기에서

내PC-> 속성 -> 고급 시스템 설정 -> 환경변수 -> 시스템변수 -> Path 를 "편집" 버튼을 누릅니다.

다음 새로 만들기를 누르신후 설치된 경로의 bin 폴더 까지 지정하여 저장합니다.

"C:\Program Files\mingw-w64\x86_64-8.1.0-win32-seh-rt_v6-rev0\mingw64\bin"













위와 같이 처리 하시고 난후 Visual Studio Code를 실행합니다.

​

실행한후 "Ctrl + `" 를 누르면 하단에 콘솔창이 뜰겁니다.

거기서 "gcc" 를 입력하면 아래와 같은 에러가 뜨면 설치가 정상적으로 된것입니다.














여기 까지 되었으면 간단한 C 프로그램을 만들어 빌드하고 실행하는 방법까지 진행 해보겠습니다.

새로운 파일을 만들어 "hello.c" 파일로 저장을 합니다.

그리고 아래의 화면처럼 코드를 작성합니다.














코드를 다 작성하고 나면 하단의 컴맨드 창에서 "gcc hello.c" 를 입력하고 엔터를 칩니다.

그리고 dir 명령을 입력 하시면 hello.c 와 a.exe 파일이 추가로 생성된것을 볼수 있습니다.

아래 창과 같이 입력 하시면 결과가 출력되는것을 확인 할수 있습니다.







Visual Studio Commmunity 를 설치 하시면 번거로움 없이 바로 코드를 작성 부터 시작 하시면 됩니다.

​

Mac에서 개발 하시는 분은 XCode가 설치 되어 있으면 컴파일러를 별도로 설치 하실 필요 없이 Visual Studio Code만 설치 하셔서 동일하게 진행하시면 됩니다.

단 컴파일 하고 나면 윈도우는 a.exe 로 나오지만 Mac에서는 a.out 으로 나옵니다. 동일하게 ./a.out 로 입력하시면 실행되는것을 확인 하실수 있습니다.

​

그럼 이만 ^^

2020년 4월 11일 토요일

MFC URLDecode 처리

오늘 이야기할 내용은 웹에서 넘겨져온 데이터를 처리할때 한글이 깨지거나 특수문자등이 깨지지 않게 처리 데이터를 받아 내리는 방법중 URLEncode 되어서 넘겨진 데이터를 DeCode 하는 방법을 이야기 할까 합니다.

URLEncode 하는 방법은 아래 링크로 확인하세요.

물론 웹에서 넘겨온 데이터가 URLEncode로 처리가 되어진 문자열 이어야 합니다.

일단 소스부터 볼께요.


BYTE ConByte(const BYTE& uc) { return uc > 57 ? uc - 55 : uc - 48; }

CString ConvertURLDecode(CString sOrg)
{
 CString sOut;
 const int nLen = sOrg.GetLength() + 1;
 register LPBYTE pOutTmp = NULL;
 LPBYTE pOutBuf = NULL;
 register LPBYTE pInTmp = NULL;
 LPBYTE pInBuf = (LPBYTE)sOrg.GetBuffer(nLen);
 //alloc out buffer
 pOutBuf = (LPBYTE)sOut.GetBuffer(nLen);

 if (pOutBuf)
 {
  pInTmp = pInBuf;
  pOutTmp = pOutBuf;
  // do encoding
  while (*pInTmp)
  {
   if ('%' == *pInTmp)
   {
    pInTmp++;
    *pOutTmp++ = (ConByte(*pInTmp) % 16 << 4) + ConByte(*(pInTmp + 1)) % 16;
    pInTmp++;
   }
   else
    *pOutTmp++ = *pInTmp;
   pInTmp++;
  }
  *pOutTmp = '\0';
  sOut.ReleaseBuffer();
 }
 sOrg.ReleaseBuffer();

 return sOut;
}
[위 소스는 Visual Studio 2017, Window 10 64bit 환경에서 빌드 되었습니다.]

소스를 보시면 아시겠지만 URLDecode는 헥사로 변환된 문자열을 다시 바이트 문자열로 변환하는 코드 입니다.

웹에서 넘겨진 데이터가 URLEncode로 변환 되어졌을경우 만든는 프로그램 환경이 UTF-8 환경이면 Decode 코드로만 처리가 되지만 Ansi 환경일 경우에는 UTF8 을 Ansi 로 바꾸는것을 Decode 하고 난후 처리 해야 한글 같은것을 정상적으로 처리 하실수 있습니다.

아래 링크도 필요하시면 확인 하시기 바랍니다.

그럼 ^^

MFC URLEncode 처리

오늘 이야기할 내용은 MFC 에서 웹으로 데이터를 보낼때 한글이 깨지거나 특수 문자 등을 처리 할때 깨지지 않고 보내기 위해서 보내는 방법중 URLEncode 처리 방법을 이야기 할까 합니다.

라이브러리를 설치 해서 쓰면 되지만 라이브러리 때문에 빌드가 안되거나 하는 상황이 많기 때문에 직접 구현 하는 방법으로 안내 할까 합니다.

​일단 소스 부터 볼께요.




BYTE ConHex(const BYTE& uc){ return uc > 9 ? uc + 55 : uc + 48; }

CString ConvertURLEncode(CString sOrg)
{
 CString sOut;
 const int nLen = sOrg.GetLength() + 1;
 register LPBYTE pOutTmp = NULL;
 LPBYTE pOutBuf = NULL;
 register LPBYTE pInTmp = NULL;
 LPBYTE pInBuf = (LPBYTE)sOrg.GetBuffer(nLen);
 //alloc out buffer
 pOutBuf = (LPBYTE)sOut.GetBuffer(nLen * 3);

 if (pOutBuf)
 {
  pInTmp = pInBuf;
  pOutTmp = pOutBuf;
  // do encoding
  while (*pInTmp)
  {
   if (isalnum(*pInTmp) || '-' == *pInTmp || '_' == *pInTmp || '.' == *pInTmp)
    *pOutTmp++ = *pInTmp;
   else
   {
    *pOutTmp++ = '%';
    *pOutTmp++ = ConHex(*pInTmp >> 4);
    *pOutTmp++ = ConHex(*pInTmp % 16);
   }
   pInTmp++;
  }
  *pOutTmp = '\0';
  sOut.ReleaseBuffer();
 }
 sOrg.ReleaseBuffer();

 return sOut;
}
[위 소스는 Visual Studio 2017, Window 10 64bit 환경에서 빌드 되었습니다.]

소스를 보시면 아시겠지만 URLEncode 는 숫자,영문,몇개의 특수문자 외의 문자열은 HEX 값으로 변환하여 전달하는 방법입니다.

물론 받는 쪽에서는 DeCode를 해서 풀어야 정상적인 문자열로 확인 할수 있습니다.

웹이랑 데이터를 주고 받기 위해서는 단순히 URLEncode 만 호출 해서 해결 할수 있지만 개발되는 프로그램 플랫폼 환경이 Ansi 환경이면 UTF8로 변환 한후 그것을 다시 URLEncode로 변환하여 전달 해야 정상적으로 웹에 전달이 됩니다.

아래 링크도 확인 하시기 바랍니다.
https://ansur.blogspot.com/2020/04/mfc-ansi-utf8.html

그럼 ^^

2020년 4월 4일 토요일

MFC UTF8 문자열 Ansi 문자열 변환.

Ansi 문자열을 UTF8 문자열로 변환하는것은 아래 포스트를 확인하시면 됩니다.
https://ansur.blogspot.com/2020/04/mfc-ansi-utf8.html

이번에 이야기 할것은 웹에서 데이터가 들어올때는 UTF8 코드 페이지로 기본적으로 들어 올겁니다.
이떄 가지고 계신 시스템이 Ansi 코드 페이지로 운영이 되시면 문자열 변환을 해야 합니다.
그 처리 방법에 대한 코드를 설명 하고자 합니다.

일단 UTF8 문자열을 Ansi 문자열로 변환 하는 코드 입니다.


BSTR    bstrWide;
char*   pszAnsi;
int     nLength;

nLength = MultiByteToWideChar(CP_UTF8, 0, sUTF8Str, lstrlen(sUTF8Str) + 1, NULL, NULL);
bstrWide = SysAllocStringLen(NULL, nLength);
MultiByteToWideChar(CP_UTF8, 0, sUTF8Str, lstrlen(sUTF8Str) + 1, bstrWide, nLength);

nLength = WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, NULL, 0, NULL, NULL);
pszAnsi = new char[nLength];
WideCharToMultiByte(CP_ACP, 0, bstrWide, -1, pszAnsi, nLength, NULL, NULL);
SysFreeString(bstrWide);

위 코드와 같이 변환을 하시면 마지막에 pszAnsi 포인터에 담긴 변수의 값을 시스템 내부에서 사용 하시면 됩니다.

코드의 처리는 먼저 UTF8로 들어온 문자열을 UniCode 형태로 변환을 합니다.
그다음 UniCode로 변환된 값을 다시 멀티 바이트로 변환 하는데 이떄 Ansi 코드 페이지를 이용하여 변환 하는 방식입니다.

그럼 ^^;

MFC Ansi 문자열 UTF8 문자열 변환

MFC는 오래된 플랫폼이죠.

그래도 이걸로 먹고 산지가 오래 되어서 ^^
요즘들어 웹이랑 데이터를 주고 받는 일이 많다 보니 웹에서는 UTF8을 기본 문자 코드로 쓰기 때문에 MFC 이전 프로젝트를 쓰시는 한글 같은것을 주고 받을때 문제가 생기기 마련입니다.​

일단 Ansi 문자열을 UTF8 문자열로 변환 하는 코드 입니다.


int  nLength, nLength2;
BSTR bstrCode; 
char* pszUTFCode = NULL;

nLength = MultiByteToWideChar(CP_ACP, 0, sAnsiStr, lstrlen(sAnsiStr), NULL, NULL); 
bstrCode = SysAllocStringLen(NULL, nLength); 
MultiByteToWideChar(CP_ACP, 0, sAnsiStr, lstrlen(sAnsiStr), bstrCode, nLength);

nLength2 = WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, pszUTFCode, 0, NULL, NULL); 
pszUTFCode = (char*)malloc(nLength2+1); 
WideCharToMultiByte(CP_UTF8, 0, bstrCode, -1, pszUTFCode, nLength2, NULL, NULL);  

위 코드와 같이 변환을 하시면 마지막에 pszUTF8 포인터에 담긴 변수의 값을 웹쪽에 전달을 하면 UTF8 형태의 문자열로 전달할수 있습니다.

코드의 처리는 먼저 멀티바이트 Ansi 코드를 UniCode로 변환을 합니다.
그다음 UniCode로 변환된 값을 다시 멀티 바이트로 변환 하는데 이때 UTF8 코드 페이지를 이용하여 변환 하는 방식 입니다.

그럼 ^^;

2020년 4월 2일 목요일

Window C++ 가용 메모리 확보하기 (Not MFC)

https://ansur.blogspot.com/2020/04/window-c.html

여기에서 MFC 기반으로 사용된 가용 메모리 확보를 알아 보았습니다.
하지만 MFC를 쓰지 않고 사용 하는 방법을 알아 보겠습니다.

일단 코드 부터 확인 하겠습니다.


#include <new>

MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);

UINT nUsageMemSize = status.ullAvailVirtual;
double fMemPercent = 0.0;

while (true)
{  
 LPBYTE lpChk = new (std::nothrow) BYTE[nUsageMemSize];
 if (lpChk == nullptr)
 {
  fMemPercent = fMemPercent == 0.0 ? 0.1 : fMemPercent*0.1;
  nUsageMemSize = (UINT)(status.ullAvailVirtual * fMemPercent);
  if (nUsageMemSize < nMinBuff)
   nUsageMemSize = nMinBuff;
 }
 else
 {
  delete[] lpChk;
  break;
 }
}

<위 코드는 Visual Studio 2013 Window 10 64bit에서 테스트 하였습니다>

기존의 포스팅 된 내용은 try catch 를 이용하여 처리를 하였는데 위 처리 방법은 std::nothrow 를 이용하여
exception 을 발생 시키지 않는 데신 메모리를 할당할수 없으면 nullptr 을 리턴 하는 점 입니다.
​

그 이후 처리 방법은 이전 포스팅을 보시면 될거 같네요 ^^

2020년 4월 1일 수요일

Window C++ 가용 메모리 확보하기

C++ 코드를 만드실때 샘플을 보시면 파일을 복사 하거나 메모리를 확보 할때 버퍼 용량을
512Byte 또는 1024Byte 로 제한된 것을 볼수 있습니다.
​
이전에 만들어진 코드를 재활용을 하다 보니 문제는 없으나 대용량 파일을 처리 하거나 메모리를 운영시에는 작은 사이즈의 버퍼를 운영 하다 보니 속도의 이슈가 생기기 마련 입니다.
윈도우에서 사용할수 있는 가용 버퍼를 확인 하는 방법을 알아 보겠습니다.


일단 코드 부터 확인 하겠습니다.


MEMORYSTATUSEX status;
status.dwLength = sizeof(status);
GlobalMemoryStatusEx(&status);
const UINT MINBUFF = 1024;
UINT nUsageMemSize = status.ullAvailVirtual;
float fMemPercent = 0.0;
  
while (true)
{
 try
 {
  LPBYTE lpChk = new BYTE[nUsageMemSize];
  if (lpChk != NULL)
  {
   delete[] lpChk;
   break;
  }
 }
 catch (CMemoryException* e)
 {
  fMemPercent = fMemPercent == 0.0 ? 0.1 : fMemPercent*0.1;
  nUsageMemSize = status.ullAvailVirtual * fMemPercent;
  if (nUsageMemSize < MINBUFF)
   nUsageMemSize = MINBUFF;
 }
}

TRACE(_T("nUsageMemSize [%u]"), nUsageMemSize);

<위 코드는 Visual Studio 2013 Window 10 64bit에서 테스트 하였습니다>
​
위코드를 실행 하시면 현재 프로그램에서 가용할수 있는 버퍼를 찾으실수 있습니다.
동작 방법은 윈도우 SDK 에서 제공하는 MEMORYSTATUSEX 구조체를 활용합니다.




위 GlobalMemoryStatusEx 함수를 이용하시면 현재 시스템의 메모리 정보를 얻어 옵니다.
제가 활용한 멤버는 현재 프로세스에 할당된 가용 메모리 항목입니다. (ullAvailVirtual)
위 항목으로 메모리 용량을 확보 하면 메모리가 할당이 안될수 있기 때문에 Exception 코드를 걸어 둬서
메모리 용량 확보에 실패 하면 원래 크기의 0.1 만큼 할당하는 로직입니다. 반복적으로 메모리 용량 확보에 실패시
0.1=>0.01=>0.001 이렇게 지속적으로 작게 메모리를 할당하여 얻을수 있는 크기를 얻어 옵니다.
​


대용량 파일을 직접 복사하는 코드를 구현 하실때 또는 기타 사항으로 처리 하시면 좋을듯 하네요. 그럼 ^^

2020년 2월 5일 수요일

VisualStudio 2017 Properties MFC Class 정보 누락

Visaul Studio 2017 을 사용중에 MFC Class 로 소스를 생성하고 작업중에

Properties 창에서 헤더 파일의 클래스를 클릭하면 해당 되는 이벤트 override 정보등이 나와야 하는데

나오지 않았다.

​
찾아 보니  C/C++ 설정창에서 기본으로 안보이게 설정이 되어 있었다.

다시 나오게 설정을 하려면.

메뉴  → Tools → Option → Text Editor → C/C++ → Advanced 에서.

"Disable Current Selection" 항목이 true 로 되어 있을건데 이것을 false 로 해주면 된다.

MFC CListCtrl Edit Label 적용

MFC CListCtrl 컨트롤 직접 생성하여 사용할때 특정 컬럼을 에디팅 하여 사용할때 처리하는 방법을
이야기 할까 합니다.

CListCtrl 에서 컬럼을 에디팅 가능하게 하기 위해서는 LVS_EDITLABELS 컨트롤 생성시 스타일 값에 추가 하셔야 합니다.

아래와 같이 코드로 생성할때는 아래와 같이 처리 하고요.


DWORD dwStyle = WS_CHILD | WS_VISIBLE | LVS_REPORT | LVS_SHOWSELALWAYS | LVS_SINGLESEL | LVS_EDITLABELS;
m_pListCtrl->Create(dwStyle, CRect(0,0,200,200), this, 1001);

리소스로 추가 하셨으면
아래의 프로퍼티 속성창에서 "Edit Labels" 를 True 속성으로 변경합니다.




다음 에디트가 활성화 되었을때 변경된 값을 핸들링 하기 위해서 CListCtrl을 가지고 있는 CWnd 기반에서 윈도우에서
아래 두가지 이벤트를 추가 합니다.

ON_NOTIFY(LVN_BEGINLABELEDIT, 1001, OnLvnBeginlabeledit)
ON_NOTIFY(LVN_ENDLABELEDIT, 1001, OnLvnEndlabeledit)

물론 함수도 추가 해야겠지요.
헤더에 아래와 같이 추가.


afx_msg void OnLvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult);
afx_msg void OnLvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult);

Cpp 파일에


void CDialogTest::OnLvnBeginlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
{
 if (m_pListCtrl == NULL) return;
 NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);

 TRACE(_T("Begin ListCtrl Edit %d\n"), pDispInfo->item.iItem);

 *pResult = 0;
}

void CDialogTest::OnLvnEndlabeledit(NMHDR *pNMHDR, LRESULT *pResult)
{
 if (m_pListCtrl == NULL) return;

 NMLVDISPINFO *pDispInfo = reinterpret_cast<NMLVDISPINFO*>(pNMHDR);

 if (pDispInfo->item.pszText != NULL)
 {
  TRACE(_T("End ListCtrl Edit %d(%s)\n"), pDispInfo->item.iItem, pDispInfo->item.pszText);
  m_pListCtrl->SetItemText(pDispInfo->item.iItem, pDispInfo->item.iSubItem, pDispInfo->item.pszText);
 }
 else
 {
  TRACE(_T("End ListCtrl Edit %d(Cancel)\n"), pDispInfo->item.iItem);
 } 

 *pResult = 0;
}

만약에 CListCtrl 에 아이템을 추가 하자 마자 에디팅 되게 모드를 바꾸시려면 아래와 같이 하시면 됩니다.


int nNew = m_pListCtrl->InsertItem(m_pListCtrl->GetItemCount(), _T(""), 0);
m_pListCtrl->SetFocus();
m_pListCtrl->EditLabel(nNew);

보통은 CListCtrl 컨트롤을 오버라이딩 하셔서 구현한 사례가 많아 오버라이딩 하지 않아도 쓸수 있는 방법을 설명해 보았습니다.
그럼 ^^