초기 이미지는 다음과 같습니다. URL 텍스트 박스에 URL을 입력하고 엔터를 입력하면, 그 URL에 대한 응답 결과를 표시합니다.


아래 이미지는 텍스트 박스 처럼 입력한 URL에 대한 응답 결과 입니다.


소스입니다.
Option Explicit

Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
Private Declare Function InternetOpenUrl Lib "wininet.dll" Alias "InternetOpenUrlA" (ByVal hInternetSession As Long, ByVal sURL As String, ByVal sHeaders As String, ByVal lHeadersLength As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
Private Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As Long, ByVal sBuffer As Long, ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long) As Boolean
Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Integer
Private Const INTERNET_OPEN_TYPE_DIRECT = 1
Private Const INTERNET_FLAG_NO_CACHE_WRITE = &H4000000
Private Const BUFFER_LEN = 256

Private Function GetUrlSource(sURL As String) As String
    Dim lReturn As Long ' 읽은 데이타의 바이트 수
    Dim hSession As Long ' WinINet 핸들
    Dim hInternet As Long ' URL을 오픈한 핸들
    Dim iResult As Long  ' 결과
    Dim sBuffer ' 읽은 데이타가 저장되는 버퍼
   
    sBuffer = String(BUFFER_LEN, " ") ' 버퍼 영역 지정
    hSession = InternetOpen("vb wininet", INTERNET_OPEN_TYPE_DIRECT, vbNullString, vbNullString, 0) ' WinINet 핸들을 얻는다
    If hSession Then hInternet = InternetOpenUrl(hSession, sURL, vbNullString, 0, INTERNET_FLAG_NO_CACHE_WRITE, 0) ' URL을 오픈한다.
    If hInternet Then
        iResult = InternetReadFile(hInternet, StrPtr(sBuffer), BUFFER_LEN, lReturn)
        GetUrlSource = MidB(sBuffer, 1, lReturn)
        Do While lReturn <> 0
            iResult = InternetReadFile(hInternet, StrPtr(sBuffer), BUFFER_LEN, lReturn)
            GetUrlSource = GetUrlSource & MidB(sBuffer, 1, lReturn)
        Loop
    End If
    GetUrlSource = StrConv(GetUrlSource, vbUnicode)
    iResult = InternetCloseHandle(hInternet)
    iResult = InternetCloseHandle(hSession)
End Function

Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer)
    If Not KeyCode = vbKeyReturn Then Exit Sub
    Text2.Text = GetUrlSource(Text1.Text)
End Sub

여기 보시면 Private Declare Function InternetReadFile Lib "wininet.dll" (ByVal hFile As Long, ByVal sBuffer As Long, ByVal lNumBytesToRead As Long, lNumberOfBytesRead As Long) As Boolean 에서 버퍼를 String로 하지 않고 Long로 표시한 이유는 VB에서 API를 사용하는 경우 String 형을 사용하게 되면 호출시 String에 저장된 무자를 유니코드로 간주 ANSI코드로 변경하고,
반환시는 거꾸로 String 형을 ANSI코드로 간주하고 유니코드로 변경하게 됩니다.
 만약 2바이트가 하나의 문자가 되는 데이터가 잘려서 저장이 되었다면 이상한 문자로 변환될수도 있읍니다. 그러면 URL에서 응답한 내용과, 저장된 내용이 다를수가 있읍니다. 그래서 URL에서 응답한 내용을 그대로 보존하기 위해 Long을 사용했읍니다. 이때는
strptr 함수를 사용해서 버퍼 문자열의 주소를 넘겨 주면 됩니다.

나머지 내용에는 별다른 특별한 내용은 없습니다.


WinInet API를 사용한다.
소스
' FTP에서 지정된 디렉토리나 파일 유무를 확인한다.
Option Explicit

Private Declare Function InternetOpen Lib "wininet.dll" Alias "InternetOpenA" (ByVal sAgent As String, ByVal lAccessType As Long, ByVal sProxyName As String, ByVal sProxyBypass As String, ByVal lFlags As Long) As Long
Private Declare Function InternetOpenUrl Lib "wininet.dll" Alias "InternetOpenUrlA" (ByVal hInternetSession As Long, ByVal sURL As String, ByVal sHeaders As String, ByVal lHeadersLength As Long, ByVal lFlags As Long, ByVal lContext As Long) As Long
Private Declare Function InternetCloseHandle Lib "wininet.dll" (ByVal hInet As Long) As Integer
Private Const INTERNET_FLAG_NO_CACHE_WRITE = &H4000000

Private Sub Command1_Click()
    Text2.Text = GetUrlSource(Combo1.Text)
    MousePointer = vbDefault
End Sub

Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer)
    If Not KeyCode = vbKeyReturn Then Exit Sub
    If Not Len(Text1.Text) > 0 Then Exit Sub
    MsgBox "URL(파일)이 존재" & IIf(CheckURL(Text1.Text), "합니다.", "하지 않습니다.") ' URL 존재 유무 검사
End Sub

Private Function CheckURL(sURL As String) As Boolean
    Dim hInternet As Long ' 오픈한 URL 핸들
    Dim hSession As Long ' WinInet 핸들
    Dim lReturn As Long ' 반환값
   
    CheckURL = False
    hSession = InternetOpen("vb wininet", 1, vbNullString, vbNullString, 0) ' WinInet을 사용하기 위해 초기화 한여, WinInet 핸들들 얻는다.
    If Not CBool(hSession) Then Exit Function ' WinInet 초기화 하지 못한 경우
    hInternet = InternetOpenUrl(hSession, sURL, vbNullString, 0, INTERNET_FLAG_NO_CACHE_WRITE, 0) ' URL 확인
    If Not CBool(hInternet) Then
        lReturn = InternetCloseHandle(hSession) ' WinInet 핸들 닫기
        Exit Function
    End If
    CheckURL = True
    lReturn = InternetCloseHandle(hInternet)
    lReturn = InternetCloseHandle(hSession) ' WinInet 핸들 닫기
End Function

실행하면 다음과 같은 창이 뜹니다.



텍스트 박스 창에 존재하는 파일의 FTP 서버의 URL을 지정하면


다음과 같이 존재하는 메세지 창을 뛰운다


존재하지 않는 파일의 FTP 서버의 URL을 지정하면


다음과 같이 파일이 존재하지 않는다는 창이 뜹니다.


파일 경로 말고, 디렉토리도 마찬가지로 가능하다. 그러나 HTTP에서는 대부분이 불가능하다고 봐야 한다.

키보드는 눌려지거나 떼어졌을 때 컴퓨터로 눌려지거나 떼어진 키 번호를 보낸다. 이 키 번호를 스캔코드(scan code)라고 한다.
그러나 scan code는 키보드 종류에 따라 다르다. 따라서 윈도우즈는 응용 프로그램 제작자들의 편의를 위해 이 스캔 코드를 가상키(virtual key)로 바꾸어준다.

MapVirtualKey API를 사용하면 가상키 값과 스캔코드 값에 대한 서로 대응 되는 값을 얻을수 있다.

다음 예는 스캔 코드 값을 상호 변환하는 예이다.
초기 화면 폼이다.


두자리 이하의 16진수 값을 입력하고 엔터를 입력하면 상호 변환된다.


다음은 위 작업에 대한 소스이다.
' 가상키값과 스캔코드값의 상호 변환, 16진수 두자리 이하 값을 입력하고 엔터 치변 상호 변환된다
Option Explicit

Private Declare Function MapVirtualKey Lib "user32" Alias "MapVirtualKeyA" (ByVal wCode As Long, ByVal wMapType As Long) As Long
Private Const MAPVK_VK_TO_VSC = 0
Private Const MAPVK_VSC_TO_VK_EX = 3

Private Sub Text1_KeyDown(KeyCode As Integer, Shift As Integer) ' 가상키값을 스캔코드 값으로
    If Not ValueCheck(Text1.Text, KeyCode) Then Exit Sub
    Text2.Text = Hex(MapVirtualKey(CLng("&h" & Text1.Text), MAPVK_VK_TO_VSC))
End Sub

Private Sub Text2_KeyDown(KeyCode As Integer, Shift As Integer) ' 스캔 코드값을 가상키값으로
    If Not ValueCheck(Text2.Text, KeyCode) Then Exit Sub
    Text1.Text = Hex(MapVirtualKey(CLng("&h" & Text2.Text), MAPVK_VSC_TO_VK_EX))
End Sub

Private Function ValueCheck(KeyValue As String, ByVal KeyCode As Long) As Boolean
    ValueCheck = False
    If Not KeyCode = vbKeyReturn Then Exit Function
    If Len(KeyValue) = 0 Then Exit Function
    If CLng("&h" & Text1.Text) = 0 Then Exit Function
    ValueCheck = True
End Function

키보드 관련 윈도우 메세지와, API 함수들 대부분은 가상키값이 사용된다.

기본 이미지입니다. 소스에서 사용한 컨트롤은 Farpoint Spread를 사용했읍니다. 다른 컨트롤을 사용해도 무방합니다.


다음 이미지는 폼을 특정 색을 투명화 시킨 것으로
이전 글의 폼의 특정 색을 투명화 하는 것과 같은 방법입니다.

다음 이미지는 투명화된 뒤에 다른 컨트롤이나 폼을 두어 컨트롤의 배경으로 투시되어 보기게 합니다.
따라서 컨트롤의 배경이 투명으로 되어 폼의 바탕이 투시되어 보이는 것처럼 됩니다.
이 글의 소스에서는 픽처박스를 사용했읍니다.



다음은 소스입니다.

우선 폼 모듈입니다.
' 컨트롤 배경 투명화시킨후, 대신 다른 배경을 보이게 하기
Option Explicit

Private Sub Form_Load()
    With Picture1 ' 픽처박스 크기를 대상 폼의 클라이언트 영역 크기로
        Picture1.Width = Me.ScaleWidth
        Picture1.Height = Me.ScaleHeight
        Picture1.Picture = Me.Picture
    End With
    Call SetParent(Picture1.hWnd, 0) ' 배경이 될 픽처박스를 바탕화면의 하위 폼으로 지정, 폼이 바탕화면의 어느 영역에든 이동 가능하면, 배경이되는 이미지도 바탕화면에서 이동이 가능해야 하므로
    Call SetWindowLong(Me.hWnd, GWL_EXSTYLE, GetWindowLong(Me.hWnd, GWL_EXSTYLE) Or WS_EX_LAYERED) ' 투명폼을 적용하기 위해, 레이어 스타일 윈도우를 적용시킨다
    SetLayeredWindowAttributes Me.hWnd, fpSpread1.BackColor, 0, LWA_COLORKEY
    Hook Me.hWnd ' 서브 클래싱
End Sub

Private Sub Form_Unload(Cancel As Integer)
    SetParent Picture1.hWnd, Me.hWnd ' 원상 복귀
    UnHook Me.hWnd
End Sub

다음은  일반 모듈 소스입니다.

Option Explicit

Public Declare Function SetParent Lib "user32" (ByVal hWndChild As Long, ByVal hWndNewParent As Long) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function GetWindowLong Lib "user32" Alias "GetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long) As Long
Public Declare Function SetLayeredWindowAttributes Lib "user32.dll" (ByVal hWnd As Long, ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwflags As Long) As Long
Private Declare Function ClientToScreen Lib "user32" (ByVal hWnd As Long, lpPoint As POINTAPI) As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal MSG As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Public Const GWL_EXSTYLE = (-20)
Private Const GWL_WNDPROC = (-4)
Public Const WS_EX_LAYERED = &H80000
Public Const LWA_COLORKEY As Long = &H1
Private Const WM_WINDOWPOSCHANGING = &H46
Private Const WM_ACTIVATEAPP = &H1C
Private Const SWP_NOACTIVATE = &H10
Private Const SWP_NOSIZE = &H1

Private Type POINTAPI
    x As Long
    y As Long
End Type

Private GetPicturePoint As POINTAPI
Private preWinProc As Long ' 이전 윈도우 프로시저 주소

Public Sub Hook(WinHwnd As Long)
    preWinProc = SetWindowLong(WinHwnd, GWL_WNDPROC, AddressOf WndProc)
End Sub

Public Sub UnHook(WinHwnd As Long)
    Call SetWindowLong(WinHwnd, GWL_WNDPROC, preWinProc)
End Sub

Public Function WndProc(ByVal hWnd As Long, ByVal MSG As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
    Select Case MSG
        Case WM_WINDOWPOSCHANGING, WM_ACTIVATEAPP
            GetPicturePoint.x = 0
            GetPicturePoint.y = 0
            ClientToScreen Form1.hWnd, GetPicturePoint
            SetWindowPos Form1.Picture1.hWnd, Form1.hWnd, GetPicturePoint.x, GetPicturePoint.y, 0, 0, SWP_NOSIZE Or SWP_NOACTIVATE ' 폼과 픽처박스가 위치하게
    End Select
    WndProc = CallWindowProc(preWinProc, hWnd, MSG, wParam, lParam)
End Function

여기서 폼이 움직일때 폼 뒤의 컨트롤이나 폼도 같이 움직일수 있도록 하기 위해서 서브 클래싱을 사용하여
WM_WINDOWPOSCHANGING 윈도우 메세지에 하단의 컨트롤(폼)도 움직이도록 반응하게 하였읍니다.

여러 상황에 대한 처리를 위한 추가적인 코드들이 필요합니다.

창(폼)에 특정 색을 투명화 시키는 예입니다.
아래 그림은 처음 폼 이미지 입니다.


다음 이미지는 특정 색을 투명화 시키기 위해 레이블의 배경색을 변경시킨 이미지 입니다.

다음 이미지, 레이블의 배경색을 투명화 시킨 이미지 입니다.  배경색을 투명화시켜서 레이블 영역의 투면화 되어 바탕화면의 이미지가 보이게 됩니다. 다른 윈도우가 아래에 있다면 그 윈도우 내용이 보이게 됩니다. 그리고 투명화 된 부분에서는 이벤트가 발생하지 않습니다.


투명화시에 폼의 캡션바의 색도 투명화시킨 색과 같은 색이 있다면 투명화 됩니다.

아래는 VB6로 구현한 소스입니다.
' 폼에 레이블을 하나 올린다
Option Explicit

Private Declare Function GetWindowLong Lib "user32.dll" Alias "GetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long) As Long ' 윈도우 속성을 얻는다.
Private Declare Function SetWindowLong Lib "user32.dll" Alias "SetWindowLongA" (ByVal hwnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long ' 윈도우 속성을 설정한다.
Private Declare Function SetLayeredWindowAttributes Lib "user32.dll" (ByVal hwnd As Long, ByVal crKey As Long, ByVal bAlpha As Byte, ByVal dwFlags As Long) As Long
Private Const LWA_COLORKEY = 1
Private Const GWL_EXSTYLE As Long = -20 ' 확장 윈도우 스타일
Private Const WS_EX_LAYERED As Long = &H80000 ' 윈도우 확장 스타일, 2000 이후 추가된 속성, 레이어드 윈도우를 생성한다.

Private Sub Form_Load()
    Label1.BackColor = &HD7E390
    Call SetWindowLong(Me.hwnd, GWL_EXSTYLE, GetWindowLong(Me.hwnd, GWL_EXSTYLE) Or WS_EX_LAYERED) ' 투명폼을 적용하기 위해, 레이어 스타일 윈도우를 적용시킨다
    SetLayeredWindowAttributes Me.hwnd, Label1.BackColor, 0, LWA_COLORKEY
End Sub

+ Recent posts