'Programming'에 해당되는 글 100건
- 2008.09.15 VC에서 소스를 어셈으로 변환
- 2008.09.12 LPARAM 생성 MAKELPARAM
- 2008.09.08 Visual C++ 완벽가이드 PPT
- 2008.09.06 [ADO] ADO 객체 정리
- 2008.09.06 [ADO] INSERT, UPDATE, DELETE 기능
- 2008.09.06 [ADO] MFC ADO 사용법
- 2008.09.05 Windows Messaging
- 2008.09.05 MFC 중복실행 방지 - Mutex
- 2008.09.04 CFileDialog사용시 경로관련 주의사항
- 2008.07.15 프로그래밍 각종링크
Visual C++ 완벽가이드 PPT
Connection 객체 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Error 객체 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Command 객체 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Parameter 객체 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Recordset 객체 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Field 객체 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
Property 객체 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
ADO를 이용한 삽입, 삭제, 업뎃
void CTestADODlg::OnButton3()
{
// DAO (Access2000) 이후 버젼 리딩가능
AfxGetModuleState()->m_dwVersion = 0x0601;
// COM이나 OLE를 라이브러리를 초기화한다.
AfxOleInit();
// ADO에 Connection 객체 사용
_ConnectionPtr pConn;
HRESULT hr;
BOOL IsConnectionOpen = FALSE;
// DB를 열기 위한 예의상 구문으로 인식하고 넘어가자.
CoInitialize(NULL);
hr = pConn.CreateInstance(__uuidof(Connection));
//pConn->CursorLocation =adUseClient;
// 데이터베이스 접속
if(SUCCEEDED(hr))
{
// Provider: 여기서는 mdb를 사용하므로, Microsoft.Jet.OLEDB.4.0를 선택한다.
// Data위치: c:\\TestDb.mdb
_bstr_t strMode("Provider=Microsoft.Jet.OLEDB.4.0;Data Source= d:\\dbTest.mdb;");
try
{
hr = pConn->Open(strMode,_bstr_t(L""),_bstr_t(L""), -1);
}
catch(_com_error& e)
{
AfxMessageBox(e.Description());
AfxMessageBox(e.ErrorMessage());
}
}
if(SUCCEEDED(hr))
{
AfxMessageBox("데이터베이스 연결됨");
IsConnectionOpen = TRUE;
}
// 데이터베이스에 연결이 되었다면,
if(IsConnectionOpen)
{
_RecordsetPtr pRs;
hr = pRs.CreateInstance(__uuidof(Recordset));
_bstr_t strQuery("Select * from tblTest");
// INSERT 구문
try
{
// 테이블명(tbltest)에서 필드ID에 200, Checker에 300을 삽입한다.
_bstr_t bstrQuery("INSERT INTO tbltest(ID,Checker) values('200','300')");
// 0L에서 0은 int형 0L은 long형을 의미한다.
// long형이 int 보다 더 큰수 저장가능
_variant_t valValue(0L);
// 새로운 트랜젝션을 시작한다.
pConn->BeginTrans();
pRs = pConn->Execute((_bstr_t)bstrQuery, &valValue, adOptionUnspecified);
// 현재 트랜젝션에서 일어난 변경을 저장하고 트랜젝션을 닫고
// 새로운 트랜젝션을 시작한다.
pConn->CommitTrans();
}
catch(_com_error& e)
{
AfxMessageBox(e.Description());
AfxMessageBox(e.ErrorMessage());
}
// UPDATE 구문
try
{
// 필드명 ID의 값이 2인 모든 곳의 필드명 ID, Checker의 필드값을 변경
_bstr_t bstrQuery2("UPDATE tbltest SET ID = 2000 , Checker = 300 WHERE ID = 2 ");
_variant_t valValue2(0L);
pConn->BeginTrans();
pConn->Execute((_bstr_t)bstrQuery2, &valValue2, adOptionUnspecified);
pConn->CommitTrans();
}
catch(_com_error& e)
{
AfxMessageBox(e.Description());
AfxMessageBox(e.ErrorMessage());
}
// DELETE 구문
try
{
// ID가 200인 tbltest 테이블 내의 Record를 삭제.
_bstr_t bstrQuery3("DELETE FROM tbltest WHERE ID = 200 ");
_variant_t valValue3(0L);
pConn->BeginTrans();
pConn->Execute((_bstr_t)bstrQuery3, &valValue3, adOptionUnspecified);
pConn->CommitTrans();
}
catch(_com_error& e)
{
AfxMessageBox(e.Description());
AfxMessageBox(e.ErrorMessage());
}
}
}
MS Access로 mdb를 만들었다고 가정하고 시작해본다.
ADO를 사용하기 위해서는 가령 작업하고 있는 파일(TestADODlg.cpp/TestADODlg.h),
라면 다음과 같은 선언을 상단에 우선적으로 해야한다.
(Step1) - 헤더파일
#if !defined(AFX_TESTADODLG_H__4B76919F_E8B6_4E36_92B4_4F549B5272FC__INCLUDED_)
#define AFX_TESTADODLG_H__4B76919F_E8B6_4E36_92B4_4F549B5272FC__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000
#import "C:\Program Files\Common Files\System\ADO\msado15.dll" rename("EOF", "EndOfFile")
using namespace ADODB;
// #import "C:\Program Files\Common Files\System\ADO\msado15.dll"no_namespace
// rename("EOF", "EndOfFile")
(Step2)
void CTestADODlg::OnTestADO()
{
// DAO (Access2000) 이후 버젼 리딩가능
AfxGetModuleState()->m_dwVersion = 0x0601;
// COM이나 OLE를 라이브러리를 초기화한다.
AfxOleInit();
// ADO에 Connection 객체 사용
_ConnectionPtr pConn;
HRESULT hr;
BOOL IsConnectionOpen = FALSE;
// DB를 열기 위한 예의상 구문으로 인식하고 넘어가자.
CoInitialize(NULL);
hr = pConn.CreateInstance(__uuidof(Connection));
pConn->CursorLocation = adUseClient;
// 데이터베이스 접속
if(SUCCEEDED(hr))
{
// Provider: 여기서는 mdb를 사용하므로, Microsoft.Jet.OLEDB.4.0를 선택한다.
// Data위치: D:\\tDbTest.mdb
_bstr_t strMode("Provider=Microsoft.Jet.OLEDB.4.0;Data Source= d:\\dbTest.mdb;");
try
{
hr = pConn->Open(strMode,_bstr_t(L""),_bstr_t(L""), -1);
}
catch(_com_error& e)
{
AfxMessageBox(e.Description());
AfxMessageBox(e.ErrorMessage());
}
}
if(SUCCEEDED(hr))
{
AfxMessageBox("데이터베이스 연결됨");
IsConnectionOpen = TRUE;
}
// 데이터베이스에 연결이 되었다면, 레코드의 내용을 확인하자.
if(IsConnectionOpen)
{
_RecordsetPtr pRs;
hr = pRs.CreateInstance(__uuidof(Recordset));
_bstr_t strQuery("Select * from tblTest");
// 레코드셋 설정
hr = pRs->Open(strQuery, pConn.GetInterfacePtr(),
adOpenForwardOnly,adLockReadOnly,adCmdText);
// 아래와 같은 방식으로 접속해도 된다
// pRs = pConn->Execute((_bstr_t)strQuery, NULL, adOptionUnspecified);
_variant_t vtColumn;
_variant_t vtNull;
// _varint_t 형의 Type을 변경한다.
vtNull.ChangeType(VT_NULL);
TCHAR strDisp[MAX_PATH+1];
short i;
// Record수를 읽는다.
long nRecord = pRs->RecordCount;
// Field수를 구한다. 주의해야할 것은 long형이라는 것이다.
long nRow = pRs->Fields->Count;
// 다음은 Field수를 구하는 다른 방법이다.
long nRow2 = pRs->GetFields()->Count;
// 필드명 표시
for(i = 0; i<nRow ; i++)
{
// 필드명 취득
vtColumn = pRs->Fields->GetItem(i)->Name;
vtColumn.ChangeType(VT_BSTR);
// 문자열 복사하는 방법
lstrcpyn(strDisp,(_bstr_t)vtColumn,MAX_PATH);
}
// 필드값 표시
while(!pRs->EndOfFile)
{
for(i=0;i<nRow;i++)
{
// 필드값을 읽어온다
vtColumn = pRs->GetCollect(i);
// 또한 필드값을 읽어오는 다른 방법이다.
// vtColumn = pRs->Fields->GetItem(i)->Value;
// 조금더 다르게 하여 특정 필드의 필드값을 읽어온다.
// vtColumn = pRs->Fields->GetItem("Checker")->Value;
// 데이터가 NULL이면 ""을 대입
if(vtColumn == vtNull)
{
vtColumn = _variant_t("");
}
else
{
vtColumn.ChangeType(VT_BSTR);
}
lstrcpyn(strDisp,(_bstr_t)vtColumn,MAX_PATH);
}
pRs->MoveNext();
}
hr = pRs->Close();
}
pConn->Close();
}
Windows Messaging
쓰래드와 메시지 : 기본 규칙
- 프로세스 하나가 10,000개에 이르는 제각기 다른 종류의 사용자 객체(아이콘, 커서, 윈도우 클래스, 메뉴, 단축키 테이블 등)를 생성할 수 있다. 한 쓰래드에서 이들 객체 중 하나를 생성하는 함수를 호출했을 때, 생성된 객체는 그 쓰래드의 프로세스가 소유하게 된다(이 말은 프로세스가 죽으면 그 객체도 함께 죽는다는 말이다).
less..
- 반면 윈도우(window)와 훅(hook) 객체는 그 윈도우를 생성하거나 훅을 설치한 쓰래드가 소유한다(이 말은 그 쓰래드가 죽으면 그 객체도 함께 죽는다는 뜻이다). -> 윈도우를 소유한 쓰래드가 그 윈도우의 모든 메시지를 관장한다. -> 하나 이상의 윈도우를 생성한 모든 쓰래드에는 메시지 큐가 할당되고, 그 때문에 그 쓰래드만의 메시지 루프를 갖게 된다.
- 또한 각각의 쓰래드는 키보드 포커스라던가, 윈도우 활성화, 마우스 캡쳐 등을 다루는 그 자신만의 환경(simulated environment)이 있다고 생각한다. 그러므로 각 쓰래드에는 이들 환경 변수를 저장할 THREADINFO 구조체가 있고, 이 구조체로써 그 쓰래드만의 붙여진(posted) 메시지 큐, 보내진(send) 메시지 큐, 응답(reply) 메시지 큐, 가상화된(virtualized) 입력 큐, wake 플래그와 그 외의 여러 환경 변수등을 식별해낼 수 있다. (메시지 큐가 하나로만 구성된 것이 아니더라..)
- 결국 THREADINFO 구조체는 윈도우즈 메시지 시스템의 주춧돌이 되더라. 하지만, UI관련 함수가 호출되기 전까지는 이 THREADINFO를 포함한 관련 리소스가 할당되지 않는다. (근데 이 구조체는 'internal', 'undocumented' 구조체라 직접 뜯어볼 수가 없다. 됀장 MS.)
- 붙여진 메시지 큐에 메시지만 넣은 다음, 그 메시지의 처리 여부에 관계없이, 바로 호출자 함수로 되돌아온다.
- POST 계열 메시지 함수 : PostMessage, PostThreadMessage(다른 쓰래드에 메시지를 붙일 때), PostQuitMessage
- 메시지를 윈도우 프로시저에 직접 보낸다. 오직 메시지가 처리되었을 때만 호출자 함수로 되돌아온다. 요러한 동기적 처리방식 때문에 주로 사용하게 된다.
- 다 른 쓰래드에 메시지를 넘길 경우 : 메시지를 보낸 쓰래드는 멈춰서서, 메시지를 받은 쓰래드가 그 메시지를 처리 완료하여 보낸 쓰래드의 응답 메시지 큐에 처리된 결과(SendMessage의 반환값)가 담긴 메시지를 붙일 때에야, 비로소 깨어나 그 결과 처리를 시작으로 다음 실행을 재개한다.
- 호출된 쓰래드에 문제가 있어 메시지를 처리 못할 경우 : 호출자 쓰래드와, 호출된 쓰래드 모두 deadlock에 걸린다! -> 이를 위해 SendMessageTimeout, SendMessageCallback, SendNotifyMessage, ReplyMessage 함수가 있는 것이다.
- SendMessageTimeOut 함수 : 보낸 메시지에 대한 응답을 받기까지의 최대 시간을 지정.
- SendMessageCallback 함 수 : 메시지를 보내고 잽싸게 되돌아온다. 호출된 쓰래드에서 메시지 처리를 마치고 응답을 보내면, 지정한 CallBack 함수가 호출된다. 호출되는 시점은 호출자 함수의 다음번에 응답 메시지 큐에서 메시질 가져올 때이다. 메시지 브로드케스팅에도 이용.
- SendNotifyMessage 함수 : 이 역시 메시지를 보내고 잽싸게 되돌아온다. 때문에 PostMessage와 비스무리할 수도 있지만, 윈도우에 직접 메시지를 보내기에 붙여진(Posted) 메시지보다 처리 우선순위가 높다.
- ReplyMessage 함 수 : (deadlock을 피하기 위해) 위의 함수들은 메시지를 보내는 측에서 호출하지만, 이 함수는 받는 쪽에서 호출한다. 이 함수를 호출한다는 것은 시스템에게 메시지 결과를 알 만큼 충분히 처리했고, 처음 메시지를 보낸 측에 결과 메시지를 싸서 보내라고 알리는 것이다. 그 결과, 처음 보낸 측은 깨어나 응답 메시지를 처리하게 될 것이야~
- 쓰래드가 GetMessage나 PeekMessage를 호출했을 때, 시스템은 그 쓰래드 큐의 상태 플래그를 검사하여 어떤 메시지를 처리할지를 결정한다. 다음은 처리 순서다.
- QS_SENDMESSAGE 플래그가 켜있으면, 시스템은 메시지를 해당 윈도우 프로시저로 보낸다. 이 때에 GetMessage와 PeekMessage역시 이 작업에 내부적으로 관여하여, 윈도우 프로시저가 그 메시지를 다 처리한 후에도 return하지 않는다. 대신에, 처리할 다음 메시지를 기다린다.
- 붙여진(posted) 메시지 큐에 메시지가 있으면, GetMessage와 PeekMessage는 이들 함수로 넘겨진 MSG 구조체를 채운다. 이 쓰래드의 메시지 루프는 보통 이 시점에서 DispatchMessage를 호출하여, 적당한 윈도우 프로시저가 그 메시지를 처리하도록 한다.
- QS_QUIT 플래그가 켜져 있으면, GetMessage와 PeekMessage는 WM_QUIT를 반환하고 QS_QUIT 플래그를 재설정한다.
- 가상화된 입력 큐에 메시지가 있으면, GetMessage와 PeekMessage는 하드웨어 입력 메시지를 반환한다.
- QS_PAINT 플래그가 켜 있으면, 이들 함수는 적당한 윈도우를 위한 WM_PAINT 메시지를 반환한다.
- QS_TIMER 플래그가 켜 있으면, 이들 함수는 WM_TIMER 메시지를 반환한다.
보 다시피, GetMessage와 PeekMessage는 보내진(send) 메시지를 처리하고 나서는 바로 반환하지 않고, 그 다음 과정으로 넘어가서야 반환한다(특히 붙여진(posted) 메시지를 처리하고나서야 반환한다). 그리고 QS_QUIT에서만 TRUE를 반환한다. 큐를 하나만 사용하는 것도 아니고, 플래그까지 사용하다니, 아주 메카니즘이 지랄같다. 아마 위 설명갖고는 이해가 다 안될 것이다. 더 공부해야..
BOOL CEasyInterfaceApp::InitInstance()
{
HANDLE hMutex = CreateMutex(NULL, TRUE, "EasyInterFace");
if(GetLastError() == ERROR_ALREADY_EXISTS)
{
ReleaseMutex(hMutex);
CWnd *pWndPrev, *pWndChild;
if(pWndPrev = CWnd::FindWindow(NULL, "EasyInterFace"))
{
pWndChild = pWndPrev->GetLastActivePopup();
if(pWndPrev->IsIconic())
pWndPrev->ShowWindow(SW_RESTORE);
pWndChild->SetForegroundWindow();
}
return FALSE;
}
ReleaseMutex(hMutex);
}
CFileDialog사용시 경로관련 주의사항
|
[질문 내용]
안녕하세요.
TipsWare 3번째 인터페이스를 사용중입니다. 다이얼로그 베이스로 개발중인데..
기본 다이얼로그 박스에서 버튼을 누르면 또 새로운 다이얼로그 박스가 뜨거든요.
근데 이 새로운 다이얼로그박스가 첨 뜰때는 이미지(로고, 체크박스, 라디오버튼 같은..)가 잘뜨는데..
기본 다이얼로그 박스에서 CFileDialog 박스로 어떤 파일을 하나 열고나면 새로운 다이얼로그박스에서
이미지들이(image 폴더에 있는) 나오지를 않네요..
제 생각에는 대충 CFileDialog에서 파일 경로가 변경되서 그런거 같은데..
어떻게 해결 해야 하는지 답변 부탁드립니다..^^;
[답변 내용]
안녕하세요~!
CFileDialog를 사용하면 내부 작업 경로가 변경되어서 이미지 파일을 정확하게 읽어 오지 못합니다.
따라서 CFileDialog를 사용하기 전에
GetCurrentPath
함수를 이용하여 현재 작업 경로를 배열에 기억시킨후에, CFileDialog 작업이 끝난후,
SetCurrentPath
함수를 이용하여 기억시킨 경로를 다시 설정해주면 됩니다.
정리하면, GetCurrentPath는 CFileDialog 를 선언하기 전에 사용해야 하구...
SetCurrentPath는 CFileDialog를 DoModal 한 이후에 사용해야 합니다.
그럼, 즐거운 하루되세요~!
[추가답변-즐거운악몽님이 답변하신 내용입니다.]
보통 CFileDialog 대화상자를 사용하다보면 간간히 경로 변경 문제로 인해 원치 않는 결과를 얻게
되기도 합니다. 일반적으로 프로그램 즉 aa.exe 를 실행 시키면 그 파일이 실행된 폴더의 위치가
작업경로가 됩니다.
예로 c:\\work\\a.exe 를 실행 시켰다면 작업경로는 c:\\work\\ 가 되죠. 이때 CFileDialog 대화상자를
이용하면 이 작업경로가 변경되곤합니다.
CFileDialog 대화상자를 DoModal() 한 후 이리저리 폴더를 움직이고나서 OK 버튼을 누르면......
그 마지막 경로가 작업경로로 지정됩니다.
예로 CFileDialog 대화상자를 호출한 후 c:\\sample\\ 이동, 그리고 OK버튼을 눌렀다면 이제부터
작업 경로는 c:\\work\\ 가 아니라 c:\\sample\\ 인 것입니다. 이때 이후부터는 상대경로를 사용한
코드를 만나게 되면 문제가 발생되는것이죠 프로그래머가 .\\\\image\\\\aa.bmp 를 로드하는 코드를
넣었다면 원래는 c:\\work\\image\\aa.bmp 를 로드 해야 하는데 CFileDialog 대화상자로 인해 작업
경로가 변경되었으니 c:\\sample\\image\\aa.bmp 를 로드 하려 시도하게 된다는 것입니다...따라서
원치 않는 작업이 이루어 지게됩니다.
따라서 CFileDialog 대화상자를 호출하는 부분에 코드에 아래와 같이 변경해 보시길 바랍니다.
char path[MAX_PATH] = {0};
//현재의 작업경로를 얻어와 저장 한다.
GetCurrentDirectory(MAX_PATH, path);
CFileDialog dlg(FALSE);
if(dlg.DoModal()==IDOK){
// 가장 마지막에 저장해 두었던 작업경로로 다시금 세팅한다.
SetCurrentDirectory(path);
// 하고픈 작업코드.....
}
혹 이미 위의 코드를 사용중이신데도 문제가 발생되는것이라면 좀더 자세한 설명 부탁드립니다...
그리고 새로이 추가하신 대화상자의 속성이 STYLE 탭에서 ......style -> POPUP 지정,
border -> None 을 지정하셨는지, 그리고 모든 CDialog 를 StandardDialog 로 변경하셨는지 체크해
보시길 바랍니다..
그럼 즐거운 하루되세요!!!
C/C++
데브피아 - 거의 왠만한 C 관련 문제는 여기서 끝남.
WinAPI - 윈도우즈 API 프로그래밍 관련 강좌 및 예제
KLDP - 오픈소스 소프트웨어 사용자 및 개발자 커뮤니티
자료구조 알고리즘 예제 소스 모음 - 여기에도 많은 양의 자료구조 예제 코드들이 있습니다.
이번에는 그냥 복사해서 어디 저장해두시는 것이 좋을 듯...
http://kuic.kyonggi.ac.kr/~skpaik/algori.html
자료구조 관련 소스 모음 - 위의 페이지와 같이 자료구조 알고리즘 관련 소스가 있습니다.
http://www.geocities.com/SiliconValley/Program/2864/ds.html
Koi4u - 정보올림피아드를 준비하는 웹사이트.
알고리즘을 공부하기 때문에 굳이 시험이 아니더라도 자료구조 알고리즘 공부하기에 좋습니다.
시험 예제도 제공하니 해보시는 것도 유익할 듯.
JAVA - 모르실 때 아래 사이트들 다 훑으면 왠만한거 다 나옵니다.
JAVA API Specifications (영문) - 자바 공식 API 소개 페이지야말로 자바 API의 경전이라고 할 수 있죠.
http://java.sun.com/reference/api/index.html
자바스터디
자바누리
JavaWorld (영문)
자바까페
MobileJAVA
열린 자바랜드
J2ee STUDY
JavaRanch (영문)
JavaService NET
김상욱 개발자 SIDE - 자바 뿐 아니라 C/C++, 리눅스, 솔라리스 강좌 등도 제공하네요.
C#
고수닷넷
http://www.gosu.net/
HOONS닷넷
http://www.hoonsbara.com/
오픈소스
코드구루 (영문)
코드 프로젝트 (영문)
소스포지 (영문)
소스코드 검색 - 코드의 일부를 검색하면 코드를 포함한 소스코드를 찾을 수 있습니다. (고건영 님 제공)
Koders
http://www.koders.com/
Google CodeSearch
http://www.google.com/codesearch
krugle
http://www.krugle.com/
codase
http://www.codase.com/
웹프로그래밍 & 기타
DebugLab.com - 디버깅의 모든 것
PHPSCHOOL - PHP 개발할 때 유용한 웹사이트
PHP 공식 웹사이트 (영문)
OK JSP
http://www.okjsp.pe.kr/bbs?act=LIST&bbs=TOOL
비주얼베이직 공개 소스 - 원래는 가입하고 포인트 지불해야 이용가능한 사이트지만
게시물을 올리신 분은 공짜로 올려두셨습니다. 물론 회원가입도 필요없음...
http://www.personaldb.net/databank/data_list.asp?group_no=2923&chk_session=Y
SQLER - SQL 공부하는 곳입니다.
taeyo's ASP & .NET
하야시의 와글와글네 (ASP, 자바스크립트 등등)
LeeChen과 함께 (다이렉트 X 프로그래밍)
gotAPI (영문) - 각종 언어의 API를 찾을 때
http://www.gotapi.com/html