요즘 윈도우 7을 사용하다보면 윈도우 창 관리 기능이 마우스를 통해 쉽고 직관적으로 할 수 있다는 점이 마음에 들었습니다.

그래서 이런 기능들을 윈도우  XP에서도 할 수 있으면 좋지 않을까 생각 해보고 윈도우7의 창 관리 기능을 지원하는 응용 프로그램을 개발해 보면 어떨가 생각해보고 만들어 보고 있습니다.

우선은 창을 끌어 상단으로 옮기면 전체화면, 오른쪽 끝이나, 왼쪽 끝으로 움직인 후 놓으면 화면의 절반을 만들어 주는 기능입니다.

우선 프로토 타입으로 만들어 보았습니다. 꽤나 유사한 기능을 할 수 있도록 만들수 있었습니다.

우선 반응이나 가능성을 보고 본격적으로 프로그램 제작을 해보도록 하겠습니다. 이와 비슷한 기능의 프로그램들이 있는가도 찾아봐야 겠네요.




아직 안정성이나 편의성에 문제가 있어서 공개하지 않고 사용할 수준이 되고 반응도 좋다면 공개하도록 하겠습니다.

멜론 스나이퍼 이후 취직한 후 별로 시간이 나지 않아 개인적인 개발을 할 수 없었다가,  이직을 하는 관계로 약간의 시간이 나서 만들어본 프로그램입니다.


저작자 표시 비영리 동일 조건 변경 허락
신고

사용자 삽입 이미지

『실용주의 프로그래머 The Pragmatic Programmer』by Andrew Hunt, David Thomas


선배로 부터 추천 받은 책이다. 프로그래밍고 관련된 일을 하고자 하는 분은 읽어 봐야만 한 책인 것 같다. 읽다 보면 공감 가는 부분도 많을 것이며, IT관련 대학생이라면 반드시 읽어봐야 할만한 책이다. 단순히 프로그램을 짜는 법만 가지고는 좋은 프로그래머가 될 수 없다.

  1. 자신의 기술craft에 관심과 애정을 가져라.
    소프트웨어 개발을 잘 해보려는 생각이 없다면 왜 인생을 그 일을 하면서 보내는가?
  2. 자신의 일에 대해 생각하면서 일하라!
    자동 조종 장치를 끄고 직접 조종하라. 스스로의 작업을 지속적으로 비판하고 평가하라.
  3. 어설픈 변명을 만들지 말고 대안을 제시하라.
    변명하는 대신 대안을 제시하라. 그 일은 할 수 없다고 말하지 말고, 무엇을 할 수 있는지에 대해 설명하라.
  4. 깨진 창문을 내버려두지 말라.
    눈에 뜨일 때마다 나쁜 설계, 잘못된 결정, 좋지 않은 코드를 고쳐라.
  5. 변화의 촉매가 되라.
    사람들에게 변화를 가용할 수는 없다. 대신 미래가 어떤 모습일지 그들에게 보여주고 미래를 만드는 일에 그들이 참여하도록 도우라.
  6. 큰 그림을 기억하라.
    주변에 무슨 일이 일어나는지 점검하는 일을 잊어버릴 정도로 세부사항에 빠지지 말라.
  7. 품질을 요구사항으로 만들어라.
    프로젝트의 진자 품질 요구사항을 결정하는 자리에 사용자를 참여시켜라.
  8. 지식 포트폴리오에 주기적으로 투자하라.
    학습을 습관으로 만들라.
  9. 읽고 듣는 것을 비판적으로 분석하라.
    벤더, 매체들의 야단법석, 도그마에 흔들리지 말라. 여러분과 여러분 프로젝트의 관점에서 정보를 분석하라.
  10. 무엇을 말하는가와 어떻게 말하는가 모두 중요하다.
    무엇을 말하는 가와 어떻게 말하는 가 모두 중요하다. 효과적으로 전달하지 못한다면 좋은 생각이 있어봐야 소용없다.
  11. DRY-반복하지 마라. Don't Repeat Yourself.
    어떤 지식 한 조갇도 하나의 시스템 안에서는 모호하지 않고, 권위 있고, 단 하나뿐인 표현을 가져야 한다.
  12. 재사용하기 쉽게만들라.
    재사용이 쉽다면, 사람들이 재사용할 것이다. 재사용을 촉진하는 환경을 만들라.
  13. 관련 없는 것들 간에 서로 영향이 없도록 하라.
    컴포넌트를 자족적이고, 독립적이며, 단 하나의 잘 정의된 목적만 갖도록 설계하라.
  14. 최종 결정이란 없다.
    돌에 새겨진 것처럼 불변하는 결정은 없다. 그렇게 생각하는 대신, 모든 결정이 해변 백사장 위에 쓴 글자와 같다고 생각하고 변화에 대비하라.
  15. 목표물을 찾기 위해 예광탄을 써라.
    예광탄은 이것저것을 시도해보고 그것들이 목표와 얼마나 가까운 데 떨어지는지 보는 방법으로 목표를 정확히 맞추게 해준다.
  16. 프로토타입을 통해 학습하라.
    프로토타이핑은 배움의 경험이다. 프로토 타이핑의 가치는 만들어낸 코드에 있지 않고, 여러분이 배운 교훈에 있다.
  17. 문제 도메인에 가깝게 프로그래밍하라.
    사용자의 언어를 사용해서 설계와 코딩을 하라.
  18. 추정을 통해 놀람을 피하라.
    시작하기 전에 추정부터 하라. 잠재적인 문제점들을 미리 찾아내게 될 것이다.
  19. 코드와 함께 일정도 반복하며 조정하라.
    구현하면서 얻는 경험을 이용해서 프로젝트의 시간 척도를 세밀하게 조정하라.
  20. 지식을 일반 텍스트로 저장하라.
    일반 텍스트 형식은 시일이 지났다고 못쓰게 되는 일이 없다. 일반 텍스트 형식은 여러분의 작업을 활용하고 디버깅과 테스팅을 쉽게 만드는 데 도움이 된다.
  21. 명령어 셸의 힘을 사용하라.
    그래픽 사용자 인터페이스로는 할 수 없는 일에 셸을 이용하라.
  22. 하나의 에티터를 잘 사용하라.
    에디터를 마치 손의 연장延長으로 자유자재로 다루어야 한다. 여러분이 사용하는 에디터는 설정을 바꿀 수 있고, 확장가능하고, 프로그램 가능해야 한다.
  23. 언제나 소스코드 관리 시스템을 사용하라.
    소스코드 관리는 여러분 작업을 위한 타임머신이다. 언제라도 과거로 돌아갈 수 있게 해준다.
  24. 비난 대신 문제를 해결하라.
    버그가 여러분 잘못인지 다른 사람 잘못인지는 별로 중요하지 않다. 그것은 여전히 여러분의 문제이며, 여전히 고쳐야 할 필요가 있다.
  25. 디버깅을 할때 당황하지 마라.
    숨을 깊게 들이고 쉬고, 무엇이 버그를 일으키는지 '생각하라!'
  26. 'select'는 망가지지 않았다.
    OS나 컴파일러의 버그를 발견하는 일은 정말 드물게 일어나며, 심지어 써드파티 제품이나 라이브러리일지라도 드문 일이다. 버그는 애플리케이션에 있을 가능성이 가장 크다.
  27. 가정하지마라. 증명하라.
    진짜 데이터와 경계 조건이 있는 실제 환경에서 여러분이 내렸던 가정들을 증명하라.
  28. 텍스트 처리 언어를 하나 익혀라.
    여러분은 하루 가운데 많은 시간을 텍스트와 씨름하며 보낸다. 왜 여러분 대신 컴퓨터가 그 일의 일부를 하게끔 만들지 않는가?
  29. 코드를 작성하는 코드를 작성하라.
    코드 생성기는 생선성을 증가시키며 중복을 막는 일에 도움이 된다.
  30. 완벽한 소프트웨어는 만들 수 없다.
    소프트웨어는 완벽할 수 없다. 피할 수 없이 나타나는 에러로부터 여러분의 코드와 사용자들을 보호하라.
  31. 계약에 따른 설계를 하라.
    코드가 실제로 하기로 한 것을 문서화하고 검증하기 위해 계약을 사용하라.
  32. 일찍 작동을 멈추게 하라.
    보통은 죽은 프로그램이 절름잘이 프로그램보다 해를 훨씬 덜 끼친다.
  33. 단정문을 사용해서 불가능한 상황을 예방하라.
    단정은 여러분이 세운 가정을 검증해준다. 확실한 것이 없는 세상에서 여러분의 코드를 보호하려면 단정문을 사용하라.
  34. 예외는 예외적인 문제에사용하라.
    예외를 잘못 쓰면 고전적 스파게티 코드의 모든 가독성과 유지보수 문제를 그대로 겪을지도 모른다. 예외는 예외적인 일들만을 위해 남겨두어라.
  35. 시작한 것은 끝내라.
    가능하다면, 리소스를 할당한 루틴이나 객체가 해제도 책임져야한다.
  36. 모듈간의 결합도를 최소화하라.
    디미터의 법칙을 적용하는 '부끄럼 타는shy'코드를 작성해서 결함이 생기는 일을 피하라.
  37. 통합하지 말고 설정하라.
    애플리케이션에서 기술 선택을 설정 옵션으로 구현하고, 통합하거나 만들어 넣지 말라.
  38. 코드에는 추상화를, 메타데이터에는 세부 내용을.
    프로그램은 최대한 일반화해서 만들고, 세부사항들은 가능하면 컴파일된 코드 기반 바깥으로 빼라.
  39. 작업흐름 분석을 통해 동시성을 개선하라.
    사용자의 흐름이 허용하는 동시성을 최대한 활용하라.
  40. 서비스를 사용해서 설계하라.
    서비스, 곧 잘 정의되고 일관성 있는 인터페이스를 통해 의사소통하는 독립적이고 동시성 있는 객체들의 관점에서 설계하라.
  41. 언제나 동시성을 고려해 설계하라.
    동시성이 가능하도록 설계하면, 더 적은 가정만 내리고서도 더 깔끔한 설계를 할 수 있다.
  42. 모델에서 뷰를 분리하라.
    애플리케이션을 모델과 뷰의 관점으로 설계해서 적은 비용만 들이고도 유연함을 얻어내라.
  43. 칠판을 사용해 작업흐름을 조율하라.
    참여하는 요소들의 독립성independence과 고립성isolation을 유지하면서도 개별적인 사실과 에이전트를 잘 조율하려면 칠판을 사용하라.
  44. 우연에 맡기는 프로그래밍을 하지 말라.
    정말 믿을 만한 것만 믿어야 한다. 우발적인 복잡함을 조심하고, 우연한 행운을 목적의식을 가지고 만든 계획과 착각하지 말라.
  45. 여러분의 알고리즘의 차수를 추정하라.
    코드를 작성하기 전에, 실행시간이 대략 얼마나 걸릴지 감을 잡아 놓아라.
  46. 여러분의 추정을 테스트하라.
    알고리즘의 수학적 분석이 모든것을 다 알려주지는 않는다. 실제 대상환경에서 코드의 수행 시간을 측정해보라.
  47. 일찍 리팩터링하고, 자주 리팩터링하라.
    정원의 잡초를 뽑고 식물 배치를 조정하는 것과 똑같이, 코드도 필요할 때면 언제라도 다시 작성하고 다시 작업하고 다시 아키텍처를 만들라. 문제의 근원을 해결하라.
  48. 테스트를 염두에 두고 설계하라.
    코드를 한 줄이라도 쓰기 전에 테스팅에 대해 생각하기 시작해야 한다.
  49. 소프트웨어를 테스트하라. 그렇지 않으면 사용자가 테스트하게 될 것이다.
    가차 없이 테스트하라. 사용자가 여러분을 위해 버그를 찾게 만들지 말라.
  50. 자신이 이해하지 못하는, 마법사가 만들어준 코드는 사용하지 말라.
    마법사는 엄청난 양의 코드를 만들 수 있다. 그것들을 프로젝트에 통합해 넣기 전에 그 코드 내용을 전부 이해하는지 확실히 해놓도록 하라.
  51. 요구사항을 수집하지 말고 채굴하라.
    요구사항이 지면에 놓여져 있는 경우는 퍽드물다. 보통은 가정과 오해, 정치政治의 지층들 속에 묻혀 있다.
  52. 사용자처럼 생각하기 위해 사용자와 함께 일하라.
    시스템이 정말로 어떻게 사용될지 통찰력을 얻을 수 있는 가장 좋은 방법이다.
  53. 구체적인 것보다 추상적인 것이 더 오래간다.
    구현 말고 추상화에 투자하라. 추상은 서로 다른 구현이나 새로운 기술의 출현 때문에 빗발치듯 생기는 변화를 견뎌내고 살아남을  수 있다.
  54. 프로젝트 용어사전을 사용하라.
    프로젝트에서 쓰이는 특정 용어와 어휘들의 유일한 출처를 만들고 유지하라.
  55. 생각의 틀을 벗어나지 말고, 틀을 찾아라.
    해결이 불가능해 보이는 문제와 마주쳤을때, 진짜 제약조건을 찾아라. 스스로에게 이렇게 물어보라. '정말로 반드시 이런 방식으로 해야 하는 일인가? 꼭 해야만 하는 일이긴 한 건가?'
  56. 준비가 되었을 때 시작하라.
    여러분은 살아오면서 경험을 쌓아 왔다. 자꾸 거슬리는 의혹을 무시하지말라.
  57. 어떤 일들은 설명하기보다 실제로 하는 것이 더 쉽다.
    명세의 나선에 빠지지 말라. 언젠가는 코딩을 시작해야 한다.
  58. 형식적인 방법의 노예가 되지 마라.
    여러분의 개발 실천 방법과 개발 능력의 맥락 안에 넣어보지 않고, 맹목적으로 어떤 기법을 채택하지 말라.
  59. 비싼 도구가 더 좋은 설계를 낳지는 않는다.
    벤더들의 과장, 어떤 분야의 도그마 그리고 가격표의 휘광에 넘어가지 말라. 도구 자체의 장점만 갖고 판단하라.
  60. 팀을 기능 줌심으로 조직하라.
    설계자와 코더를, 테스트 담당자와 데이터 모델 담당자를 분리시키지 말라. 코드를 만드는 방식에 맞춰 팀을 만들어라.
  61. 수작업 절차를 사용하지 말라.
    셸 스크립트나 배치 파일은 똑같은 명령을, 똑같은 순서로, 어느 때라도 반복해서 실행해준다.
  62. 일찍 테스트하고, 자주 테스트하라. 자동으로 테스트하라.
    매번 빌드할 때마다 실행되는 테스트가 책꽂이의 테스트 계획보다 훨씬 효과적이다.
  63. 모든 테스트가 통과하기 전에 코딩이 다된게 아니다.
    뭐 더 할 말 있나?
  64. 파괴자를 써서 테스트를 테스트하라.
    코드의 별도 복사본을 만들고, 그 복사본에 고의로 버그를 넣은 다음 테스트가 잡아내는지 검증하라.
  65. 코드 커버리지보다 상태 커버리즈를 테스트 하라.
    중요한 프로그램 상태들을 파악해서 테스트하라. 단지 많은 코드 줄 수를 테스트 범위 안에 넣는 것만으로는 충분하지 않다.
  66. 버그는 한번만 잡아라.
    인간 테스터가 버그를 찾아 내면, 그 때가 인간 테스터가 그 버그를 찾는 마지막 순간이 되어야 한다. 그 순간 이후 부터는 자동화된 테스트가 그 버그를 담당하도록 만들라.
  67. 한국어도 하나의 프로그래밍 언어인 것처럼 다루라.
    코드를 작성하는 것처럼 문서도 작성하라. DRY 원칙을 존중하고, 메타데이터를 사용하고,MVC 모델을 쓰고, 자동생성을 이용하고 등등.
  68. 문서document가 애초부터 전체의 일부가 되게하고, 나중에 집어넣으려고 하지 말라.
    코드와 떨어져서 만든 문서가 정확하거나 최신 정보를 반영하기는 더 힘들다.
  69. 사용자의 기대를 부드럽게 넘어서라
    사용자들이 무엇을 기대하는지 이해한 다음, 그것보다 약간 더 좋은 것을 제공하라.
  70. 자신의 작품에 서명하라.
    옛날 장인들은 자신의 작업 결과물에 서명하는 일을 자랑스럽게 여겼다. 여러분도 마찬가지여야 한다.


체크리스트

  • 배울만한 언어
    C, C++, 자바에 식상했는가? CLOS, Dylan, Eiffel, Objective C, Prolog, Smalltalk 혹은 을 공부해보라. 각 언어마다 서로 다른 능력과 다른 '맛'이 있다. 집에서 이들 언어 가운데 하나 또는 여러 개를 이용한 자그마한 프로젝트를 시작해보라.
  • WISDOM 놀이
    무엇(What)을 배우길 원하는가?
    말하려는 것에서 그들의 관심(interest) 있어 하는 건 무엇인가?
    얼마나 소양(sophisticated)이 있는가?
    어느정도 구체적인(detail) 내용을 원하는 가?
    누가 정보를 소유(own)하길 원하는가?
    그들이 경청하도록 동기(motivate)를 주려면 어떻게 해야 할까?
  • 직교성을 유지하는 방법
    독립적이고, 잘 정의된 컴포턴트를 설계하라.
    코드의 결합도를 줄여라.
    전역 데이터를 피하라.
    비슷한 함수들을 리팩터링하라.
  • 프로토타입을 만들 것들
    아키텍처
    기존시스템에 추가할 새로운 기능
    외부 데이터의 구조 혹으은 내용
    써드파티 도구나 컴포턴트
    성능 문제
    사용자 인터페이스 설계
  • 아키텍처에 관련된 질문
    책임이 잘 정의 되었는가?
    협력이 잘 정의 되었는가?
    결합도는 최소화되었는가?
    잠재적 중복을 찾아낼 수 있는가?
    인터페이스 정의와 제약 사항은 수용할 만 한가?
    모듈이 필요한 데이터에 필요한 때 접근 할 수 있는가?
  • 디버깅 체크리스트
    보고된 문제가 내재하는 버그의 직접적 결과인가 아니면 단순히 증상일 뿐인가?
    보그가 정말로 컴파일러에 있나? OS에 있나? 혹은 여러분 코드에 있나?
    이 문제를 동료에게 상세히 설명한다면 어떻게 말하겠는가?
    의심이 가는 코드가 단위 테스트를 통과한다면, 테스트는 충분히 완전한 것인가? 이 데이터로 단위 테스트를 돌리면 무슨 일이 생기는가?
    이 버그를 야기한 조건이 시스템의 다른 곳에도 존재하는가?
  • 디미터 함수 법칙
    어떤 객체의 메서드는 오직 다음 목록에 들어있는 메서드들만 호출해야한다.

    자기자신
    전달받은 매개 변수
    자신이 생성한 객체
    컴포넌트 객체
  • 의도적으로 프로그래밍하는 방법
    지금 자신이 무엇을 하고 있는지 항상 의식하라.
    맹목적으로 코딩하지 말라.
    게획을 세우고 그것을 바탕으로 진행하라.
    신뢰할 수 있는 것에만 기대라.
    여러분이 내린 가정을 문서로 남겨라.
    코드뿐 아니라 가정도 테스트하라.
    노력의 우선순위를 정하라.
    과거의 노예가 되지 말라.
  • 언제 리팩터링을 해야 하는가
    DRY 원칙의 위반을 발견했을 때
    더 직교성이 좋게 만들 수있는 것들을 찾았을 때
    여러분의 지식이 더 나아졌을 때
    요구사항이 진화했을 때
    성능을 향상시킬 필요가 있을 때
  • 고르디우스의 매듭을 자르기

    불가능해 보이는 문제를 풀때, 스스로에게 다음처럼 질문해보라.

    더 쉬운 방법이 존재하는가?
    지금 진짜 문제를 푸고 있는가?
    왜 이것이 문제인가?
    무엇이 이것을 어렵게 만드는가?
    반드시 이 방법으로 해야 하는건가?
    반드시 해야 하는 일이긴 한가?
  • 테스트의 유형
    단위 테스트
    통합테스트
    유효성 평가validation와 검증verification
    자원 고갈, 에러 그리고 복구
    성능 테스트
    사용편의성 usability 테스트
    테스트 자체를 테스트하기
신고
Qt는 크로스 컴파일이 가능한 GUI개발 라이브러리이다.

자바처럼 한번의 소스코드 개발로 여러 운영체제에서 동일하게 작동한다. 자바는 컴파일도 한번만 하면 바이트코드 프로그램이 완성되지만..

Qt의 경우는 운영체제 별로 다시 컴파일 해야 한다. 하지만 네이티브로 실행되는 바이너리 파일이 만들어지게 된다..

물론 운영체제별로 약간 다르게 작동 할수 있겠지만 당연히 작동 결과에 대한 차이가 있을 경우에는 API문서에 포함 되어 있다. API문서도 비교적 깔끔하게 잘 정리 되어있다.

특별히 소스 수정없이 여러 운영체제에서 안정적으로 돌아 갈 수 있다.

그리고 오픈소스 프로그램을 개발 할땐 GPL라이센스로 무료로 이용할 수 있다. 상용 라이센스 가격은 정확히 모르겠으나 MS쪽이랑 비슷하거나 약간 더 저렴한 거 같았다..

Qt라이브러리 쓰기위해서 http://trolltech.com/ 로 가서 Qt With MinGW 받아서 깔면 된다.
하지만 여기에는 디자이너 툴은 포함되어있지만, 소스를 편집하기 위한 IDE툴이 없다. 따라서 Eclipse CDT나 다른 프로그램이 필요하다.

하지만 Visual Studio 가 익숙해 VS에서 사용하려면~~?? 인터넷에서 흔하게 Visual Studio에서 개발하고 MS 컴파일러로 컴파일 까지 하는 문서들은 있었지만..MS컴파일러로 컴파일 해야할 이유까지는 없었다.. 근냥 편집툴로만 MS Visual Studio를 쓰고 싶었다..

우선 PATH를지정 해야 한다.
Qt 4.3 Command Prompt 아이콘을 클릭하면 자동으로 패스가 지정된다. 하지만 우리가 원하는 것은 VS에서 Qt를 컴파일 하기 위한 것이므로 내 컴퓨터 등록정보에서 환경 변수를 등록해야 한다..
사용자 삽입 이미지

QTDIR = C:\Qt\4.3.1
PATH =  C:\Qt\4.3.1\bin;C:\MinGW\bin
QMAKESPEC = win32-g++


위와같이 환경 변수를 추가 한다.

Microsoft Visual Studio를 실행 하여
File- New - Project... 메뉴를 선택한다.
사용자 삽입 이미지
Visual C++ 카테고리에서 Makefile Project를 선택 한다.

사용자 삽입 이미지

마법사 대화 상자가 뜨면 우선 Finish를 누른다. 컴파일 명령어는 메뉴에서 다시 지정하도록 합니다.

Project - Property메뉴를 선택한다..
왼쪽 트리에서 Configuration Properties - NMake를 선택합니다.

사용자 삽입 이미지

Build Command Line오른쪽에 있는 [...]버튼을 눌러서 아래와 같이 입력한다.

qmake -project
qmake
make
사용자 삽입 이미지

Rebuild All Command Line라인과  Clean command Line에는 " make clean "등의 명령을 적절히 넣으면된다.

Output은 실행 파일이 생성될 위치이다..
기본적으로 Release 폴더 밑에 폴더 이름으로 실행파일이 생긴다.. 거기에 맞춰 입력 하면 된다.

Output은 "Release\프로젝트명.exe" 이렇게 주면 되다..

기본적인 설정을 마쳤다..

Solution Exploler Tool Windows에서 프로젝트를 선택하고 오른쪽 버튼을 눌러 Add- New Item을 선택한다.
사용자 삽입 이미지

C++ File 을 선택한다..
#include <QApplication>
#include <QLabel>
int main(int argc, char *argv[])
{
     QApplication app(argc, argv);
     QLabel *label = new QLabel("Hello Qt!");
     label->show();
     return app.exec();
}


위와 같이 한번 입력해보고 컴파일 실행 버튼을 눌러보자... 컴파일과 실행이 되었었을 것이다.

하지만 Qt 라이브러리에 대한 인텔리센스는 작동하지 않을 것이다. 그럴 경우.. Tools에 Options...
Project and Solution - VC++ Directory - Include File에서 Qt관련 include가 있는 곳에 폴더를 지정해 준다..

{QTDIR}\include\ActiveQt
{QTDIR}\include\Qt
{QTDIR}\include\Qt3Support
{QTDIR}\include\QtAssistant
{QTDIR}\include\QtCore
{QTDIR}\include\QtDBus
{QTDIR}\include\QtDesigner
{QTDIR}\include\QtGui
{QTDIR}\include\QtNetwork
{QTDIR}\include\QtOpenGL
{QTDIR}\include\QtScript
{QTDIR}\include\QtSql
{QTDIR}\include\QtSvg
{QTDIR}\include\QtTest
{QTDIR}\include\QtUiTools
{QTDIR}\include\QtXml


위와 같이 폴더를 추가하면 인테리센스가 작동한다. 한결 편하게 작업 할 수 있을 것이다..

신고
운영체제 시간에 배운 스풀~~ 내가만든 프로그램에 직접 적용 해보았다..

요즘 만들고 있는 멜론 스나이퍼~~ 그 프로그램에 스풀을 써보았다.

프로그램 메인 쓰레드와 함께 변환 쓰레드, 스풀 쓰레드가 작동한다.

사용자 삽입 이미지
(테스트 : 204MByte , MP3파일 30개)


기존 버젼은 파일 변환 후.. 전송이 완료된 후에야 다음 변환에 들어간다.

하지만 스풀을 사용한 후 파일 변환후, 전송은 스풀에 모두 맡겨 버리고 다음 파일 변환으로 바로 넘어간다.

역시 느린 플래쉬 메모리를 가진 MP3P로 보낼 경우 무려 36%나 빨라졌다.

학교에서 이론만으로 배운 내용을 실제 적용해 봤다는 것에 매우 뜻깊다. 물론 적용 기념으로 벤치마킹도했다. 시간을 측정하지 않더라도 채감 할 수 있는 향상이 있었다..;;




컴퓨터 전공이 아니라도 프린터 스풀은 들어 보았을 것이다.

스풀이라는 것은 느린 입출력 장치로 데이터를 보내고 받을 때 직접 보내지 않고 스풀에 맡기는 방식이다.

한글에서 프린트 버튼을 누르고 진행 그래프가 순식간에 100%가 되고 사라진다. 하지만 아직 프린트는 열심히 프린트 하고 있을 것이다.

사용자 삽입 이미지

한글에서 프린트를 누르면 스풀 프로그램에 프린트 할것을 맡긴다. 스풀은 받은 문서를 프린트보다 훨씬 빠른 하드디스크에 쓴다. 매우 빠르 시간에 완료 될 것이다.

문서를 받은 스풀 프로그램은 계속 해서 하드디스크에 저장해둔 문서를 프린트한다.

그리고 한글은 스풀에다 문서 인쇄에 대한 것을 모두 맡겼으니... 프린팅이 완료되지 않아도 다른 기능을 계속 수행 할 수 있다.

즉 자원을 활용도를 극대화 할 수 있다.

아~! 그리고 버퍼라는 말도 들어봤을 것이다. 버퍼가 아마도 더 익숙하지 않을 까 생각한다.

버퍼란 느린 장치와 빠른 장치와의 서로 데이터를 주고 받을 때 원할 하게 수행하기 위한 중간 저장공간이다.

버퍼랑 스풀은 기능상으로는 동일하다. 하지만 특별히 디스크를 중간 저장공간으로 쓸 경우 일반적으로 스풀이라고 말한다.
신고

김정민님이 어떻게 윈도우를 찾느냐고 물어보셔서~~ 작성합니다.. 많은 도움이 되었으면 좋겠네요..

CMelOnSniperMacro는 매크로를 수행하는 클래스입니다.

이 클래스의 맴버변수로는 변환해야할 파일들 현재 몇번째 파일 변환중인지.. 몇번째 스텝인지 등을 저장하는 변수들이 있습니다.

다이어로그 클래스에서 실제 이 Macro클래스 인스턴스가 만들어집니다.. 타이머에 의해 m_DoMacro맴버 함수가 정해진 시간에 호출 됩니다. 맴버 변수가 가지고 있는 현재 상태를 가지고 매크로를 수행하는 부분입니다.

그 중 윈도우창을 찾는 부분의 소스들입니다. 중복되는것은 생략했습니다.
 

bool CMelOnSniperMacro::m_FindMainWindow(void)
{
 m_wndMelon.m_hWnd = ::FindWindow(TEXT("MelOnFrameV30"),NULL);
 if(m_wndMelon.m_hWnd == false) return false;
 return true;
}

::FindWindow(TEXT("MelOnFrameV30"),NULL); 이 함수는
첫번째 인자로 윈도우의 클래스 이름
두번째 인자는 캡션 이름
으로 윈도우를 찾고 핸들을 반환합니다.. 최상위 윈도우를 찾을 수 있습니다. NULL을 입력 할 수 있습니다.

m_wndMelonCWnd타입입니다.

만약 윈도우 내부에 있는 자식 윈도우를 찾고자 하거나 특정 윈도우 다음에 위치한 윈도우를 얻고자 할때 는
FindWindowEx(HWND, HWND, LPCWSTR, LPCWSTR);함수를 사용하시면 됩니다..
첫번째 인자는 부모 윈도우의 핸들
두번째 인자는 인자 윈도우에 다음에 위치하는 윈도우 핸들을 얻어 옵니다.
세번째 인자는 클래스명
네번쨰 인자는 캡션 명입니다..

물론 NULL값을 인자로 넘겨 줄 수 있습니다.

int CMelOnSniperMacro::m_DoMacro()
{
 
 switch(m_nStep)
 {
  case 2://찾아보기창 띄우기
  //컨버팅 변환창에서 파일 찾기 버튼 누르기
  {
   CWnd* wndDCFConverting =m_findWindow(TEXT("#32770"), _T(""), 530,455);
   if(wndDCFConverting->m_hWnd != NULL){
    wndDCFConverting->PostMessage(WM_COMMAND,0x836,0x0);
    m_nStep++;
   }
   delete(wndDCFConverting);
  }
  break;
 }
 return 0;
}

그러나 멜론 3.0으로 업데이트 되면서 대부분의 윈도우에 캡션이 없습니다. 특이 윈도우 디자인에 이미지가 많은 경우 대부분 FindWindow로 한번에 찾기 어렵습니다..

또한 클래스명 또한 다이얼로그 박스에 기본값인 #32770입니다. 따라서 같은 클래스명과 이름의 윈도우가 수개 내지 수십개가 됩니다.

그래서 윈도우를 구별하기위해 윈도우 크기를 가지고 윈도우를 찾는 함수 m_findWindow라는 함수를 구현 했습니다... 물론 이 방법은 윈도우크기가 고정되어 바꿀 수 없는 윈도우에 한해서 쓰일 수 있는 방법입니다.. 윈도우 크기가 바뀔수 있는 경우라면 또 다른 방법을 생각 해봐야겠죠..

CWnd* wndDCFConverting =m_findWindow(TEXT("#32770"), _T(""), 530,455);

윈도우를 받아 옵니다.

    wndDCFConverting->PostMessage(WM_COMMAND,0x836,0x0);

혹시 윈도우를 찾지 못할 수도 있으므로 if문을 사용 찾은 경우에만 원하는 메세지를 찾은 창에 보냅니다. 위 다른 윈도우에 명령을 보내는 방법은 PostMessageSendMessage함수 가 있습니다.

PostMessage는 비동기로 메세지를 보내고 SendMessage는 동기로 메세지를 보냅니다..

이 함수의 인자, Msg와 wParam, lParam의 값은 Spy++이나 별도의 유틸을 통해서 쉽게 얻을 수 있습니다. WM_COMMAND, 0x836, 0x0은 멜론 스나이퍼에서 [파일찾기] 버튼을 눌러주는 역활을 합니다.

아래가 윈도우의 크기로 창을 얻어오는 함수의 실제 구현입니다.

CWnd* CMelOnSniperMacro::m_findWindow( CString strClass, CString strWindow, int height, int width)
{
 CWnd* findWindow = new CWnd();
 
 do{  
  findWindow->m_hWnd = ::FindWindowEx(NULL,findWindow->m_hWnd,strClass, strWindow);
  RECT r;
  //창의 크기로 윈도우 판별함
  findWindow->GetWindowRect(&r);
  int thisHeight = r.bottom-r.top;
  int thisWidth = r.right - r.left;
  if(thisHeight == height && thisWidth==width){
   return findWindow;
  }

 }while(findWindow->m_hWnd != NULL);

 findWindow->m_hWnd = NULL;
 return findWindow;
}


findWindow->m_hWnd = ::FindWindowEx(NULL,findWindow->m_hWnd,strClass, strWindow);
우선 가장 처음 do{}while()반복무을 수행할 경우 findWindow->m_hWndNULL입니다.. 따라서 해당 클래스이름과 윈도우명을 가진 첫번째 윈도우를 찾습니다..

그 다음 윈도우크기를 비교해 크기까지 동일하면 우리가 찾으려 했던 윈도우이므로~~ 해당 윈도우를 반환하고..

만약 윈도우 크기가 다르면 다음 윈도우를 찾아야합니다.

do{}while()반복문이 처음이 두번째 수행되는 것이라면  findWindow->m_hWnd가 이전에 찾았던 윈도우입니다.

FindWindowEx에서 두번째 인자가 이 다음 윈도우를 찾아라 하는 인자입니다.. 그럼으로 두번째 해당윈도우 클래스명과 이름을 가지는 두번째 윈도우를 찾게 되는 것입니다.
findWindow->m_hWnd = ::FindWindowEx(NULL,findWindow->m_hWnd,strClass, strWindow);

계속 해서 찾다가 더이상 다음 윈도우가 없을경우~~ null을 반환하고 while()문을 빠져 나오게 됩니다..
신고


VC6.0에서는 기본 설치 옵션이 유니코드를 사용하지 않는다. 따라서 설치시 유니코드를 사용하도록 옵션을 지정해주거나, 이미 설치를 하였다면 설치시디의

E:\VC98\MFC\LIB

에서 라이브러파일을 모두 복사해온다.

Project-Setting-C/C++탭에서 Processor Defination:항목의 _MBSC를 _UNICODE로 바꿔준다.

Link탭으로 이동한후 Category DropDown List에서 Output을 선택한후 Entry-point Symbol의 값에wWinMainCRTStartup를 입력하면된다.

Shared DLL을 사용할경우 DLL파일을 열수 없다는 에러가 뜨네요.. Static linked libary를 사용하는게 편할것 같네요..
신고

일명 매크로 프로그램을 만드는 방법을 간단히 소개하겠다.

가장 먼저해야 할 일은 제어하고자 하는 프로그램의 핸들을 얻어 오는 것이다.

Spy+프로그램을 이용하면 쉽게 찾을 수 있다.

사용자 삽입 이미지

창 찾기 창이 뜨면 찾기 도구를 드래그 하여 원하는 응용 프로그램에 끌어 놓는다. FindWindow로는 최상위 부모 윈도우만 찾을 수 있다. 제어하고자 하는 응용프로그램에 최상위 윈도우에 끌어다 놓는다.
사용자 삽입 이미지


원하는 프로그램을 선택하면 아래와 같이 윈도우 정보가 표시 된다. 여기서 캡션과 클래스를 통해 원하는 윈도우를 찾을 수 있다.
사용자 삽입 이미지

파일-로그 메세지 메뉴을 이용해 창을 찾은후 확인을 누르면 현재 윈도우가 어떠한 메세지를 받는지 모두 볼 수 있다. 여기서 발생하는 이벤트중 키보드, 또는 마우스 관련 이벤트를 확인 하면 된다.
사용자 삽입 이미지


using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;

using System.Runtime.InteropServices;


namespace WindowsApplication1
{

    public partial class Form1 : Form
    {
        //사용할 API함수를 임포트 한다.
        [DllImport("USER32.DLL")]
        public static extern uint FindWindow(string lpClassName,
            string lpWindowName);

        [DllImport("user32.dll")]
        public static extern uint FindWindowEx(uint hWnd1, uint hWnd2, string lpsz1, string lpsz2);

        [DllImport("user32.dll")]
        public static extern uint SendMessage(uint hwnd, uint wMsg, uint wParam, uint lParam);

        [DllImport("user32.dll")]
        public static extern uint PostMessage(uint hwnd, uint wMsg, uint wParam, uint lParam);

        uint handle;


        private void button3_Click(object sender, EventArgs e)
        {
           //핸들을 찾는다. Spy+를 통해 찾은 클래스 이름과 캡션을 이용하면 된다. 둘 중 하나만 알경우에도 찾을 수 있다. 그때는 하나의 인자를 null로 넘겨 주면된다.
            handle = FindWindow("SciCalc", "계산기");
          //찾은 핸들에서 자식 윈도우 핸들을 찾기 위해서는 FindWindowEx를 이용한다.
            handle = FindWindowEx(handle, 0, "Shell DocObject View", null);
            handle = FindWindowEx(handle, 0, "Internet Explorer_Server", null);
            label1.Text = handle.ToString();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //찾은 핸들을 통해 메세지를 보낸다. 여기서는 아래 16진수들 의 값은 스파이 메세지 로그에서 찾은 값을 이용하면 된다. 여기서는 키를 누른 메세지(탭키누른후 엔터키를 누른다.)를 보내는 예제 이다.
            PostMessage(handle, 0x0100, 0x9, 0xF0001);
            PostMessage(handle, 0x0101, 0x9, 0xC00F0001);
            PostMessage(handle, 0x0100, 0xD, 0x1C001);
            PostMessage(handle, 0x0102, 0xD, 0xC01C001);
           
        }
}


FindWindow 함수는 윈도우를 찾는 API 함수이다. 첫번째 인자는 실행중인 프로그램의 클래스 이름이고 두번째 인자는 프로그램의 타이틀이다. 최상위 부모 윈도우만 찾을 수 있고 자식 윈도우는 FindWinowEx를 통해 찾으면 된다.

FindWindowEx는 부모윈도우 핸들을 통해 부모 윈도의 자식 핸들을 구하는 함수 이다. 예를 들면 프로그램에 자식으로 붙어 있는 버튼등을 찾으려면 FindWindowEx를 이용하면 된다. 첫번째 인자는 부모 핸들이다.

두번째 인자는  처번째 인자의 자식핸들 값 또는 0 값이 오면 된다. 만약 핸들 값이 들어오면 들어온 두번째 핸들 값 이후의 자식만 검색한다. 0 이면 모든 윈도우의 자식을 검색한다.

세번째 인자는 클래스 이름, 네번째 인자는 프로그램타이틀명이다.

PostMessage와 SendMessage는 메세지를 보내는 함수이다. 이 함수를 실행함으로서 원하는 제어를 할 수 있다.
첫번째 인자는 메세지를  보내고자하는 윈도우 핸들의 값이고, 두번째 인자는 보내고자 하는 메세지, 세번째 인자는 wParam ,네번째 인자는 lParam이다. lParam ,wParam은 메세지의 부가정보라고 할수 있다.  WM_LBUTTONDOWN메세지가 발생할때는 마우스의 버튼이 눌러진 위치 등의 부가 정보가 필요한데 이러한 정보를 실어보내는 인자이다. 역시 Spy+를 통해 확인이 가능하다.

PostMessage와 SendMessage의 차이점은 거의 없는데 PostMessage로 보내게 되면 메세지를 해당 윈도우에 던지고 바로 리턴하는 함수이고 SendMessage는 메세지를 보낸후 그 메세지가 처리된후 리턴된다. SendMessage동기화가 필요할때 사용하면 되고, 동기화 필요없이 메세지만 보내려면 PostMessage를 이용하면된다.
신고


티스토리 툴바